文章目录
- ArrayList 构造方法拷贝
- 运行1000次耗时 1ms
- for循环拷贝
- 运行1000次耗时 14ms
- Stream流 collect实现拷贝
- 运行1000次耗时 54ms
- Stream流+spring的BeanUtils实现拷贝
- 运行1000次耗时 2468 ms
- Hutool工具实现拷贝
- Hutool 5.7.13版本运行1000次耗时 64674 ms
- Hutool 5.8.24版本运行1000次耗时 15874 ms
- JSON序列化
- 运行1000次 耗时 3387 ms
- 结论
测试背景
在项目中很多地方需要拷贝对象集合、A类型对象的集合转换到B类型这种操作,但是这种操作的完成是有各种写法的,每种写法的性能可能不一样,因此对比一下各个写法的性能差异,选择最优解。
对一个有1000个对象的List复制1000次
ActivityCouponVO 对象有35个字段,各类型都有
/**
* 集合大小
*/
private int len = 1000;
/**
* 循环次数
*/
private int loop = 1000;
List<ActivityCouponVO> getList(int len){
// ... 生成一千个这个对象的集合,且每个字段赋值了
}
测试方法完整代码示范如下,后续各种方式的代码只写一次复制的代码示意,不写外层循环和耗时打印这些了
ArrayList 构造方法拷贝
底层使用了Arrays.copyOf()方法,这个方法底层又用了System.arraycopy方法,这个方法是native方法,使用本地实现,(一般为c++),直接操作内存复制,效率高
注意:new ArrayList<>(list)、Arrays.copyOf()、System.arraycopy这三个都是浅拷贝!!!
List<ActivityCouponVO> list = getList(len);
ArrayList<ActivityCouponVO> activityCouponVOS = new ArrayList<>(list);
运行1000次耗时 1ms
for循环拷贝
这个直接add 对象 也是浅拷贝,拷贝的是对象的内存地址
如果要深拷贝则循环的时候每次new一个新的对象并复制属性值
List<ActivityCouponVO> list = getList(len);
List<ActivityCouponVO> collect = new ArrayList<>(len);
for (ActivityCouponVO activityCouponVO : list) {
collect.add(activityCouponVO);
}
运行1000次耗时 14ms
Stream流 collect实现拷贝
浅拷贝
List<ActivityCouponVO> list = getList(len);
List<ActivityCouponVO> collect = list.stream().collect(Collectors.toList());
运行1000次耗时 54ms
Stream流+spring的BeanUtils实现拷贝
这种拷贝方式是第一层属性深拷贝,嵌套的对象是浅拷贝
List<ActivityCouponVO> list = getList(len);
List<ActivityCouponVO> activityCouponVOS = list.stream().map(o -> {
ActivityCouponVO activityCouponVO = new ActivityCouponVO();
BeanUtils.copyProperties(o, activityCouponVO);
return activityCouponVO;
}).collect(Collectors.toList());
运行1000次耗时 2468 ms
Hutool工具实现拷贝
这种拷贝方式是第一层属性深拷贝,嵌套的对象是浅拷贝
List<ActivityCouponVO> list = getList(len);
List<ActivityCouponVO> activityCouponVOS = BeanUtil.copyToList(list, ActivityCouponVO.class);
Hutool 5.7.13版本运行1000次耗时 64674 ms
(看了下源码是因为加锁了)
Hutool 5.8.24版本运行1000次耗时 15874 ms
(新版本里没有加锁了,而且还做了优化,例如properties缓存)
JSON序列化
完全深拷贝
JSONObject.parseArray(JSONObject.toJSONString(list), ActivityCouponVO.class);
运行1000次 耗时 3387 ms
结论
不需要深拷贝时建议使用
Arrays.copyOf()
System.arraycopy
这种本地实现的拷贝数组方式
深拷贝时可以使用for循环、stream流、BeanUtils工具等方式实现,但是要注意使用工具的时候看看工具的源码实现,有可能里面有锁,然后有性能的坑~