java 高效深度拷贝_Java几种深度拷贝方法效率比较

java在复制一个对象时有浅拷贝与深拷贝之分,具体区别就不在此赘述,本文主要分析java深拷贝的几种方法以及他们的效率高低。

1. 使用java序列化方法

想要深拷贝一个对象,常用的方法是序列化为数据流,此方法的前提是对象以及对象中包含的子对象都要继承serializable接口。

2. 利用kryo序列化框架

kryo是一个快速高效的java序列化框架,旨在提供快速、高效和易用的api。无论文件、数据库或网络数据kryo都可以随时完成序列化。kryo还可以执行自动深拷贝(克隆)、浅拷贝(克隆)。这是对象到对象的直接拷贝,非对象->字节->对象的拷贝。该方法不需要继承serializable接口。

com.esotericsoftware

kryo

4.0.1

3. 利用json转化的方法

如果对象没有继承serializable接口,可以先将对象转化为json,再序列化为对象,和第一种方法类似。json转换工具可以用jackson或者json-lib,本文选择json-lib只需要在maven里面添加以下依赖:

net.sf.json-lib

json-lib

2.4

jdk15

4. 手动new对象的方法

人工构建对象,如果需要复制的对象中包含非基本类型,如list,对象等结构时,可以在需要的时候手动new对象,将属性值挨个调用set方法,比较繁琐。

5. 具体实例

(1) 首先构造两个实体对象user.java和name.java,具体代码如下

public class user implements serializable{

private static final long serialversionuid = -6952319891279734655l;

private name name;

private string phone;

private string sex;

private int age;

...//此处省略get、set方法

}

public class name implements serializable{

private static final long serialversionuid = -2023200990550843496l;

private string firstname;

private string lastname;

...//此处省略get、set方法

}

(2) 测试的主程序代码如下:

package com.test.sort.hello;

/**

* created by geekboy on 2017/12/10.

*/

import java.io.bytearrayinputstream;

import java.io.bytearrayoutputstream;

import java.io.objectinputstream;

import java.io.objectoutputstream;

import com.esotericsoftware.kryo.kryo;

import net.sf.json.jsonobject;

/**

* @author geekboy

*

*/

public class testcopy {

public static void main(string[] args) {

user source=new user();

source.setage(25);

source.setphone("13590117892");

source.setsex("1");

name name=new name();

name.setfirstname("li");

name.setlastname("ming");

source.setname(name);

long before=system.currenttimemillis();

for(int i=0;i<1000000;i++){

user tmp=copybynewobject(source);

try {

//user tmp=copyimplserializable(source);

//user tmp=copybyjson(source);

} catch (exception e) {

e.printstacktrace();

}

}

long after=system.currenttimemillis();

system.out.println(after-before);

}

/**

* 深层拷贝 - 需要类继承序列化接口

* @param

* @param obj

* @return

* @throws exception

*/

@suppresswarnings("unchecked")

public static t copyimplserializable(t obj) throws exception {

bytearrayoutputstream baos = null;

objectoutputstream oos = null;

bytearrayinputstream bais = null;

objectinputstream ois = null;

object o = null;

//如果子类没有继承该接口,这一步会报错

try {

baos = new bytearrayoutputstream();

oos = new objectoutputstream(baos);

oos.writeobject(obj);

bais = new bytearrayinputstream(baos.tobytearray());

ois = new objectinputstream(bais);

o = ois.readobject();

return (t) o;

} catch (exception e) {

throw new exception("对象中包含没有继承序列化的对象");

} finally{

try {

baos.close();

oos.close();

bais.close();

ois.close();

} catch (exception e2) {

//这里报错不需要处理

}

}

}

/**

* 深层拷贝 - 需要net.sf.json.jsonobject

* @param

* @param obj

* @return

* @throws exception

*/

@suppresswarnings("unchecked")

public static t copybyjson(t obj) throws exception {

return (t)jsonobject.tobean(jsonobject.fromobject(obj),obj.getclass());

}

/**

* 通过new 对象的方法深拷贝

* @param source

* @return

*/

public static user copybynewobject(user source){

user result=new user();

result.setage(source.getage());

result.setphone(source.getphone());

result.setsex(source.getsex());

name name=new name();

name.setfirstname(source.getname().getfirstname());

name.setlastname(source.getname().getlastname());

result.setname(name);

return result;

}

/**

* 通过kryo框架深拷贝

* @param source

* @return

*/

public static user copybykryo(user source){

kryo kryo = new kryo();

return kryo.copy(source);

}

}

6. 运行结果及效率分析

new 对象

jdk序列化

kyro序列化

json转化

1000次

1

237

307

477

10000次

3

914

790

1328

100000次

10

2951

1780

2604

通过上面的测试可以看出new 对象的方法是最快的,比较适合性能要求较高的场合。其次是kyro序列化方法,json转化的方法还有优化的余地,使用不同的json库会有不同结果。最慢的是jdk的序列化操作,不建议用此种方案进行深度拷贝。

参考文献

希望与广大网友互动??

点此进行留言吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值