通常大家都用Hutool工具的BeanUtil类来进行list集合拷贝:
官网:Hutool — 🍬A set of tools that keep Java sweet.
Hutool是一个小而全的Java工具类库,既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;
- Web开发
- 与其它框架无耦合
- 高度可替换
BeanUtil使用实例:
private void copyDemo(User user, List<User> list) {
//hutool list拷贝
List<UserBO> listHutool = cn.hutool.core.bean.BeanUtil.copyToList(list,UserBO.class);
//hutool 对象拷贝
UserBO test = cn.hutool.core.bean.BeanUtil.copyProperties(user,UserBO .class);
//BeanUtil 对象拷贝 自己封装的BeanUtil方法
UserBO userBO = BeanUtil.copyProperties(user, UserBO.class);
//BeanUtil list拷贝
List<UserBO> list2 = BeanUtil.copyPropertiesOfList(list, UserBO.class);
}
但是,Hutool的BeanUtil类使用了大量反射,用他来进行list拷贝,性能略有影响,如果对性能有所要求,可以考虑使用Orika,来进行list拷贝。
Orika 是一个 Java Bean 映射框架,可以将两个不同类对象进行转换,特别是不同API时,常常会遇到实体转换。
关于Orika性能为什么快的源码分析:Orika源码分析:性能为什么这么快 - 简书
关于Orika使用:orika core工具对实体(Bean)进行深度拷贝 - miaoying - 博客园
在实际开发中,进行不同对象转换时,可以根据自己的需要选择转换工具类。
朋友们,发现了Orika的坑,Orika会偶发性出现父类拷贝不了的情况,看了源码也没看出个所以然,最后还是用了BeanUtil
个人封装的BeanUtil
public class BeanUtil {
private BeanUtil() {
//do nothing
}
public static final Map<String, BeanCopier> BEAN_COPIER_CACHE = new ConcurrentHashMap<>();
public static final Map<String, ConstructorAccess> CONSTRUCTOR_ACCESS_CACHE = new ConcurrentHashMap<>();
public static void copyProperties(Object source, Object target) {
BeanCopier copier = getBeanCopier(source.getClass(), target.getClass());
copier.copy(source, target, null);
}
private static BeanCopier getBeanCopier(Class sourceClass, Class targetClass) {
String beanKey = generateKey(sourceClass, targetClass);
BeanCopier copier = null;
if (!BEAN_COPIER_CACHE.containsKey(beanKey)) {
copier = BeanCopier.create(sourceClass, targetClass, false);
BEAN_COPIER_CACHE.put(beanKey, copier);
} else {
copier = BEAN_COPIER_CACHE.get(beanKey);
}
return copier;
}
/**
* 两个类的全限定名拼接起来构成Key
*
* @param sourceClass
* @param targetClass
* @return
*/
private static String generateKey(Class<?> sourceClass, Class<?> targetClass) {
return sourceClass.getName() + targetClass.getName();
}
public static <T> T copyProperties(Object source, Class<T> targetClass) {
T t = null;
try {
t = targetClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new BeanCopyException(String.format("Create new instance of %s failed: %s", targetClass, e.getMessage()));
}
copyProperties(source, t);
return t;
}
public static <T> List<T> copyPropertiesOfList(List<?> sourceList, Class<T> targetClass) {
if (sourceList == null || sourceList.isEmpty()) {
return Collections.emptyList();
}
ConstructorAccess<T> constructorAccess = getConstructorAccess(targetClass);
List<T> resultList = new ArrayList<>(sourceList.size());
for (Object o : sourceList) {
T t = null;
try {
t = constructorAccess.newInstance();
copyProperties(o, t);
resultList.add(t);
} catch (Exception e) {
throw new BeanCopyException(e);
}
}
return resultList;
}
private static <T> ConstructorAccess<T> getConstructorAccess(Class<T> targetClass) {
ConstructorAccess<T> constructorAccess = CONSTRUCTOR_ACCESS_CACHE.get(targetClass.getName());
if (constructorAccess != null) {
return constructorAccess;
}
try {
constructorAccess = ConstructorAccess.get(targetClass);
constructorAccess.newInstance();
CONSTRUCTOR_ACCESS_CACHE.put(targetClass.toString(), constructorAccess);
} catch (Exception e) {
throw new BeanCopyException(String.format("Create new instance of %s failed: %s", targetClass, e.getMessage()));
}
return constructorAccess;
}
}