拷贝简单对象的四种方法及性能分析

前言

实际项目中,我们常常需要对对象进行拷贝,此文将列出四种常见的对象拷贝方式,并针对它们分别做出实验进行性能分析。

此次实验用于拷贝的简单对象如下:

class CurrencyDailyBo implements Serializable {
    private static final long serialVersionUID = 1L;
    private int id;
    private Date day;
    private double amountMoney;
    private int businessNum;
    private int balanceNum;
    private Integer type;
    private String createTime;
    private String modifyTime ;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public Date getDay() {
        return day;
    }
    public void setDay(Date day) {
        this.day = day;
    }
    public double getAmountMoney() {
        return amountMoney;
    }
    public void setAmountMoney(double amountMoney) {
        this.amountMoney = amountMoney;
    }
    public int getBusinessNum() {
        return businessNum;
    }
    public void setBusinessNum(int businessNum) {
        this.businessNum = businessNum;
    }
    public int getBalanceNum() {
        return balanceNum;
    }
    public void setBalanceNum(int balanceNum) {
        this.balanceNum = balanceNum;
    }
    public String getCreateTime() {
        return createTime;
    }
    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getModifyTime() {
        return modifyTime;
    }
    public void setModifyTime(String modifyTime) {
        this.modifyTime = modifyTime;
    }
    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}

方法一、getset方法

最原始拷贝对象的方法,new一个新对象,然后进行get,set方法拷贝属性,代码如下:

@Test
    public void getset() {
        CurrencyDailyBo currencyDailyBo = new CurrencyDailyBo();
        currencyDailyBo.setAmountMoney(111);
        currencyDailyBo.setBalanceNum(1);
        currencyDailyBo.setBusinessNum(2);
        currencyDailyBo.setCreateTime("today");
        currencyDailyBo.setModifyTime("today");
        currencyDailyBo.setDay(new Date());
        currencyDailyBo.setId(1111111);
        currencyDailyBo.setType(1);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            CurrencyDailyBo copyBo = new CurrencyDailyBo();
            copyBo.setType(currencyDailyBo.getType());
            copyBo.setId(currencyDailyBo.getId());
            copyBo.setDay(currencyDailyBo.getDay());
            copyBo.setAmountMoney(currencyDailyBo.getAmountMoney());
            copyBo.setBalanceNum(currencyDailyBo.getBalanceNum());
            copyBo.setBusinessNum(currencyDailyBo.getBusinessNum());
            copyBo.setCreateTime(currencyDailyBo.getCreateTime());
            copyBo.setModifyTime(currencyDailyBo.getModifyTime());
        }
        long cost = System.currentTimeMillis() - start;
        System.out.println("get,set方法拷贝10万个简单对象,耗时====" + cost);
    }

运行结果:

get,set方法拷贝10万个简单对象,耗时====15


方法二、beanutils工具类拷贝

第二种方法我们使用apache提供的工具类(spring也提供了类似的工具类)beanutils.copyProperties来进行拷贝,其底层实现原理为反射,代码如下:

@Test
    public void beanutilsForCopy() throws InvocationTargetException, IllegalAccessException {
        CurrencyDailyBo currencyDailyBo = new CurrencyDailyBo();
        currencyDailyBo.setAmountMoney(111);
        currencyDailyBo.setBalanceNum(1);
        currencyDailyBo.setBusinessNum(2);
        currencyDailyBo.setCreateTime("today");
        currencyDailyBo.setModifyTime("today");
        currencyDailyBo.setDay(new Date());
        currencyDailyBo.setId(1111111);
        currencyDailyBo.setType(1);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            CurrencyDailyBo copyBo = new CurrencyDailyBo();
            BeanUtils.copyProperties(copyBo, currencyDailyBo);
        }
        long cost = System.currentTimeMillis() - start;
        System.out.println("beanutils工具类拷贝10万个简单对象,耗时====" + cost);
    }

运行结果:

beanutils工具类拷贝10万个简单对象,耗时====3495


方法三、通过json字符串转入转出

第三种方法我们通过fastjson将对象转入json字符串,再使用parseObject转出为对象,代码如下:

@Test
    public void jsonForCopy() {
        CurrencyDailyBo currencyDailyBo = new CurrencyDailyBo();
        currencyDailyBo.setAmountMoney(111);
        currencyDailyBo.setBalanceNum(1);
        currencyDailyBo.setBusinessNum(2);
        currencyDailyBo.setCreateTime("today");
        currencyDailyBo.setModifyTime("today");
        currencyDailyBo.setDay(new Date());
        currencyDailyBo.setId(1111111);
        currencyDailyBo.setType(1);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            String json = JSON.toJSONString(currencyDailyBo);
            CurrencyDailyBo copyBo = JSON.parseObject(json, CurrencyDailyBo.class);
        }
        long cost = System.currentTimeMillis() - start;
        System.out.println("jsonString拷贝10万个简单对象,耗时====" + cost);
    }

运行结果:

jsonString拷贝10万个简单对象,耗时====374

此方法还可用于原被拷贝对象为map集合的情况。


方法四、重写clone方法

这种方法在实际项目中较少使用,它是通过实现cloneable接口及重写clone方法来拷贝对象,但它的效率是最高的,有条件的情况下可以使用该方法。对于复杂对象(嵌套、链表等)来说,必须对其子对象也实现clone方法,否则拷贝结果会丢失子对象的属性数据,代码如下:

    @Test
    public void cloneForCopy() {
        CurrencyDailyBo currencyDailyBo = new CurrencyDailyBo();
        currencyDailyBo.setAmountMoney(111);
        currencyDailyBo.setBalanceNum(1);
        currencyDailyBo.setBusinessNum(2);
        currencyDailyBo.setCreateTime("today");
        currencyDailyBo.setModifyTime("today");
        currencyDailyBo.setDay(new Date());
        currencyDailyBo.setId(1111111);
        currencyDailyBo.setType(1);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            Object copyBo = currencyDailyBo.clone();
        }
        long cost = System.currentTimeMillis() - start;
        System.out.println("clone方法拷贝10万个简单对象,耗时====" + cost);
    }

重写对象:

class CurrencyDailyBo implements Serializable ,Cloneable{
    private static final long serialVersionUID = 1L;
    private int id;
    private Date day;
    private double amountMoney;
    private int businessNum;
    private int balanceNum;
    private Integer type;
    private String createTime;
    private String modifyTime;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public Date getDay() {
        return day;
    }
    public void setDay(Date day) {
        this.day = day;
    }
    public double getAmountMoney() {
        return amountMoney;
    }
    public void setAmountMoney(double amountMoney) {
        this.amountMoney = amountMoney;
    }
    public int getBusinessNum() {
        return businessNum;
    }
    public void setBusinessNum(int businessNum) {
        this.businessNum = businessNum;
    }
    public int getBalanceNum() {
        return balanceNum;
    }
    public void setBalanceNum(int balanceNum) {
        this.balanceNum = balanceNum;
    }
    public String getCreateTime() {
        return createTime;
    }
    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getModifyTime() {
        return modifyTime;
    }
    public void setModifyTime(String modifyTime) {
        this.modifyTime = modifyTime;
    }
    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

运行结果:

clone方法拷贝10万个简单对象,耗时====0




四、总结

通过以上测试,我们可以发现传统的get、set方法,复制10万个基本对象耗时15毫秒,以此为标准,jsonstring方式耗时大约稳定在getset方法的20倍左右。再次是beanutils方法,耗时基本稳定在getset方法的200倍左右,此方法不建议使用,因为它的功能使用json可以完全代替,而它的耗时最长。最后,重写clone方法来拷贝对象效率是最高的,但实现不易,复杂对象的拷贝需使所有子对象都实现clone方法,实际项目中较少使用。

以上是拷贝简单对象的四种方法及各自性能分析,个人水平有限,如有意见建议,请多多留言。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值