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 |
参考文献 【Java几种深度拷贝方法效率比较】http://blog.csdn.net/isea533/article/details/9375907
https://github.com/EsotericSoftware/kryo
镜像地址 http://www.zhangwei.wiki/#/posts/1

文章图片
转载于:https://www.cnblogs.com/coderzhw/p/11094284.html
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 事件代理
- Java|Java OpenCV图像处理之SIFT角点检测详解
- java中如何实现重建二叉树
- 《深度倾听》第5天──「RIA学习力」便签输出第16期
- 数组常用方法一
- 【Hadoop踩雷】Mac下安装Hadoop3以及Java版本问题
- Java|Java基础——数组
- RxJava|RxJava 在Android项目中的使用(一)
- java之static、static|java之static、static final、final的区别与应用