FastByteArrayOutputStream和ByteArrayOutputStre。。。
原型模式中要实现深拷贝对象,⼀般是要重写clone()⽅法,因为有⼀些对象是没有实现Cloneable接⼝的,⽐如
String,Integer,BigDecimal,这些常⽤的类都没有实现Cloneable接⼝。
但是很多情况下,如果重写clone()⽅法实现深拷贝,⼜会重新new对象(为了使引⽤对象指向是⼀个新的内存地址),像下⾯这样:
@Override
protected User clone() throws CloneNotSupportedException {
User cloneUser = (User) super.clone();
cloneUser.setAge(new Integer(this.age));
cloneUser.setId(new Long(this.id));
cloneUser.setMoney(new toString()));
cloneUser.setName(new String(this.name));
return cloneUser;
}
这就有点违背了原型模式的初衷,原型本来就是为了避免new对象时进⾏复杂的构造,这⾥重写clone()不仅没有避免,并且有new对象了。
这种情况下,我们就要使⽤对象序列化的⽅式来实现深拷贝,⽽最为推荐的是FastByteArrayOutputStream和ByteArrayOutputStream 对象来实现深拷贝。
那么他们到底效率怎么样呢?
上代码:
这是要拷贝的对象:
public class User implements Serializable,Cloneable{
private Integer age;
private String name;
private Long id;
private BigDecimal money;
public BigDecimal getMoney() {
return money;
}
public void setMoney(BigDecimal money) {
< = money;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
public void setId(Long id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(age, user.age) &&
Objects.equals(name, user.name) &&
Objects.equals(id, user.id) &&
Objects.equals(money, );
}
@Override
public int hashCode() {
return Objects.hash(age, name, id, money);
}
public User() {
this.age = 0;
this.name = "";
this.id = 1L;
< = BigDecimal.ZERO;
}
public User(Integer age, String name, Long id, BigDecimal money) {        this.age = age;
this.name = name;
this.id = id;
< = money;
}
}
下⾯是拷贝⼯具类:
public class  GetModelUtil {
private static FastByteArrayOutputStream fastByteArrayOutputStream;    private static ObjectOutputStream outputStreamOfFast;
private static ObjectInputStream objectInputStreamOfFast;
private static ByteArrayOutputStream commonbyteArrayOutputStream;    private static ByteArrayInputStream commonbyteArrayInputStream;
private static ObjectOutputStream outputStreamOfCommon;
private static ObjectInputStream objectInputStreamOfCommon;
// 为了提⾼效率,事先初始化内存输出对象
static {
fastByteArrayOutputStream = new FastByteArrayOutputStream();        commonbyteArrayOutputStream = new ByteArrayOutputStream();    }
bigdecimal转换为integer/
/ FastByteArrayOutputStream 拷贝
// FastByteArrayOutputStream 拷贝
public static Object fastDeepClone(Object orig) throws IOException {
Object obj = null;
try {
// 初始化 ObjectOutputStream 输出流对象
outputStreamOfFast = new ObjectOutputStream(fastByteArrayOutputStream);
// 写⼊对象到字节数组中,进⾏序列化
outputStreamOfFast.writeObject(orig);
// 刷新输出流
outputStreamOfFast.flush();
/
/从这个拷贝对象的流中获取输⼊流
objectInputStreamOfFast = new InputStream());
//从输⼊流中读出这个对象
obj = adObject();
// 因为测试的时候要多次读写,所以不关闭输⼊流和输出流
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
//返回拷贝的对象
return obj;
}
// ByteArrayOutputStream 拷贝
public static Object commonDeepClone(Object orig) throws IOException {
Object obj = null;
try {
// 初始化 ObjectOutputStream 输出流对象
outputStreamOfCommon = new ObjectOutputStream(commonbyteArrayOutputStream);
// 将指定的对象写⼊字节数组输出,进⾏序列化
outputStreamOfCommon.writeObject(orig);
// 刷新输出流
outputStreamOfCommon.flush();
// 使⽤字节数组初始化 ByteArrayInputStream 输⼊流对象
commonbyteArrayInputStream = new ByteArray());            // 使⽤字节数组初始化 ByteArrayInputStream 输⼊流对象
objectInputStreamOfCommon = new ObjectInputStream(commonbyteArrayInputStream);
// 从内存中读出对象
obj = adObject();
// 因为测试的时候要多次读写,所以不关闭输⼊流和输出流
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
//返回拷贝的对象
return obj;
}
}
测试代码:
public static void main(String[] args) throws IOException, CloneNotSupportedException {
User user = new User();
user.setAge(11);
user.setId(12L);
user.setName("花花");
long commonCloneStart = System.currentTimeMillis();
for (int i = 0 ; i <= 1000 ; i++){
User userOfClone = (User) GetModelUtilmonDeepClone(user);
}
System.out.println("使⽤ByteArrayOutputStream深克隆花费时间:" + (System.currentTimeMillis() - commonCloneStart));
long fastCloneStart = System.currentTimeMillis();
for (int i = 0 ; i <= 1000 ; i++){
User userOfClone = (User) GetModelUtil.fastDeepClone(user);
}
System.out.println("使⽤FastByteArrayOutputStream深克隆花费时间:" + (System.currentTimeMillis() - fastCloneStart));
}
运⾏结果:
使⽤ByteArrayOutputStream深克隆花费时间:224
使⽤FastByteArrayOutputStream深克隆花费时间:57
很明显,使⽤FastByteArrayOutputStream拷贝对象效率明显⾼于ByteArrayOutputStream。
原因:
FastByteArrayOutputStream内部实现由⼀个LinkedList<byte[]>组成,每⼀次扩容中分配⼀个数组的空间,并当该数据放⼊到List中。需要分配的数组长度为调⽤FastByteArrayOutputStream的write⽅法决定。⽽ByteArrayOutputStream内部实现为⼀个数组每⼀次扩容需要重新分配空间并将数据复制到新数组中,这就是FastByteArrayOutputStream⽐ByteArrayOutputStream主要区别。
FastByteArrayOutputStream 部分源码
public class FastByteArrayOutputStream extends OutputStream {
private static final int DEFAULT_BLOCK_SIZE = 256;
/
/ The buffers used to store the content bytes
private final LinkedList<byte[]> buffers = new LinkedList<>();
...
}
ByteArrayOutputStream部分源码:
public class ByteArrayOutputStream extends OutputStream {
/**
* The buffer where data is stored.
*/
protected byte buf[];
...
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。