基于CGLIB高性能LIST集合对象复制工具类

本文对比了Java中CGLIB、dozer、orika等工具在对象复制上的性能,特别是针对list集合对象的复制。实验结果显示,CGLIB在性能上表现最优,而自定义的CGLIB扩展方法在复制list集合时,性能远超其他工具。

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的情况下,如果在使用的时候创建,那速度基本没眼看了。

大量数据可能性能上会有偏差,但我没空测试了,仅供参考。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值