1.前言
java开发少不了RO、DTO、VO之类的对象复制,大部分都是基于各类框架提供的方法,比如
CGLIB
dozer
orika
Apache BeanUtils
Apache PropertyUtil
Spring BeanUtils
之类的,性能上最强的目前不容置疑的是CGLIB,和手动set、get速度基本一致,甩其他工具几条街,但可能是我用的不熟悉,始终没有找到可以复制list集合对象的方法。
所以在这里我自己手动扩展了下,代码不算优雅,但性能上比其他工具类强上很多。
2.CGLIB
private static final ConcurrentHashMap<String, BeanCopier> mapCaches = new ConcurrentHashMap<>();
/**
*
* @param source 原数据,list集合
* @param target 接收复制的数据实体类属性,会自动转换成list集合
* @param sourceKey 原数据的实体类属性,为了防止空数据获取该属性报错
* @param <O>
* @param <T>
* @return
*/
public static <O, T> List<T> listCopyMapper(List<O> source, T target, O sourceKey) {
String baseKey = generateKey(sourceKey.getClass(), target.getClass());
BeanCopier copier;
if (!mapCaches.containsKey(baseKey)) {
copier = BeanCopier.create(sourceKey.getClass(), target.getClass(), false);
mapCaches.put(baseKey, copier);
} else {
copier = mapCaches.get(baseKey);
}
List<T> targets = new ArrayList<>();
try {
source.stream().forEach(
bean -> {
T instance = null;
try {
instance = (T) target.getClass().getDeclaredConstructor().newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
copier.copy(bean, instance, null);
targets.add(instance);
}
);
} catch (Exception e) {
log.error("list bean复制失败" + e.getMessage());
}
return targets;
}
开启服务器一条数据简单测试了下,一次替换大概在6万纳秒左右,有时候会波动下,但大概不变。
同样的替换成spring的BeanUtils,大概在13万纳秒左右,偶尔波动到20多万纳秒。
偶然发现了orika有个直接复制list的,工具类大概长这样
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import java.util.List;
public class MapperUtils {
static {
mapperFactory = new DefaultMapperFactory.Builder().build();
}
private static MapperFactory mapperFactory;
public static <S, D> List<D> mapAsList(Iterable<S> source, Class<D> destinationClass) {
return mapperFactory.getMapperFacade().mapAsList(source, destinationClass);
}
}
引入jar
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.5.2</version>
</dependency>
这个封装的不错,但实际性能就差强人意了,基本18、20w纳秒出头,有时候能蹦到30w纳秒,这还是在静态代码块提前创建mapperFactory的情况下,如果在使用的时候创建,那速度基本没眼看了。
大量数据可能性能上会有偏差,但我没空测试了,仅供参考。