一、前言
实际开发中,经常会遇到对象拷贝的需求,本文就结合日常开发过程中,使用到的浅拷贝技术,进行性能比较,看看谁更强。
重要: 下面将会花大量篇幅,列出各种类型浅拷贝的代码,你可以直接拖到文章末尾,看性能对比结果。然后再根据你中意的对象回过头来看它的代码,避免疲劳。
源码链接:https://github.com/jitwxs/blog-sample/tree/master/SpringBoot/shallow_copy
首先创建一个用于拷贝的 Bean,如下所示:
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import java.util.Date;
@Data
@Builder
public class User {
private long id;
private int age;
private String name;
private boolean isMale;
private School school;
private Date createDate;
public static User mock() {
return User.builder()
.id(RandomUtils.nextLong())
.age(RandomUtils.nextInt())
.name(RandomStringUtils.randomAlphanumeric(5))
.isMale(RandomUtils.nextBoolean())
.school(new School(RandomStringUtils.randomAlphanumeric(5), RandomUtils.nextInt()))
.createDate(new Date())
.build();
}
}
@AllArgsConstructor
class School {
private String name;
private int code;
}
然后编写一个模板类,给各个浅拷贝方法提供预热和耗时统计功能:
public abstract class BaseCopyTest {
public List<User> prepareData(int size) {
List<User> list = new ArrayList<>(size);
IntStream.range(0, size).forEach(e -> list.add(User.mock()));
return list;
}
public User prepareOne() {
return User.mock();
}
public void testCopy(List<User> data) {
warnUp();
long startTime = System.currentTimeMillis();
copyLogic(data);
System.out.println(name() + ": " + (System.currentTimeMillis() - startTime) + "ms");
}
abstract void warnUp();
abstract void copyLogic(List<User> data);
abstract String name();
}
二、工具类
首先介绍下工具类这边,代表“工具类”参赛的选手有:
Apache BeanUtils
——廉颇老矣Spring BeanUtils
——夕阳红Spring BeanCopier
——三十而立Spring BeanCopier + Reflectasm
——身强力壮
2.1 Apache BeanUtils
Apache BeanUtils
算是一个比较古老的工具类,其自身是存在性能问题的,阿里巴巴开发手册中也明确禁止使用该工具,本次对比仍然把它加进来把。
想要用它需要导入依赖包:
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
public class ApacheBeanUtilsTest extends BaseCopyTest {
@Override
void warnUp() {
User source = prepareOne();
try {
User target = new User();
System.out.println(source);
BeanUtils.copyProperties(target, source);
System.out.println(target);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
void copyLogic(List<User> data) {
for(User source : data) {
try {
BeanUtils.copyProperties(new User(), source);
} catch (Exception e)