本文正在参加「Java主题月 – Java 开发实战」,详情查看 活动链接
开篇
这是我参与更文挑战的第1天,活动详情查看: 更文挑战
在开发中你有没有遇到过一些关于集合复制的问题?
普通的集合复制只是将内存中栈的地址块拷贝一份,使得一个新的集合对象指向这个地址块,但是集合中的对象变量却是指向堆中的同一块区域。所以当拷贝的集合修改了自己集合对象内的数据时,源集合对象也随之改变了,这样的效果我们称之为Java集合对象的浅复制(即只是在栈中拷贝了,而堆中的数据并没有拷贝。)
而深复制则是同时将栈中和堆中的数据进行拷贝,这样其拷贝的集合和被拷贝的集合就没有任何关系了。
案例演示
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Demo {
private int demoValue;
}
复制代码
试验一下浅复制:
@Test
public void testDemoCopy() {
// 这里我创建了一个源集合
ArrayList<Demo> sourceCollection = new ArrayList<Demo>();
// 这里我向sourceCollection添加了一些对象
sourceCollection.add(new Demo(1));
sourceCollection.add(new Demo(2));
// 这里我创建了一个新的空集合
ArrayList<Demo> newCollection = new ArrayList<Demo>();
newCollection.addAll(sourceCollection);
// 现在我修改了新集合中的一些对象
newCollection.get(0).setDemoValue(3);
// 现在我们验证它在源集合中是什么
for(Demo demo : sourceCollection){
System.out.println(demo.getDemoValue());
}
// 断言验证源Collection是否被修改.
Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1);
}
复制代码
很明显,
newCollection
中改变的Demo
对象在SourceCollection
中也跟着改变了,这说明两个集合中的Demo
对象是同一个对象。这也是浅复制所存在的弊端。
那么如何将两个集合独立开来呢,即如何进行深度复制?
试验一下深复制:
首先我们先对Demo类作一下处理,使其实现Cloneable
接口,并重写它的clone
方法
protected Demo clone() throws CloneNotSupportedException {
return (Demo)super.clone();
}
复制代码
测试类如下
@Test
public void testCopyDeep() throws Exception{
ArrayList<Demo> sourceCollection = new ArrayList<Demo>();
sourceCollection.add(new Demo(1));
sourceCollection.add(new Demo(2));
ArrayList<Demo> newCollection = new ArrayList<Demo>();
for(Demo demo : sourceCollection){
// 这里是重点
newCollection.add(demo.clone());
}
newCollection.get(0).setDemoValue(3);
for(Demo demo : sourceCollection){
System.out.println(demo.getDemoValue());
}
Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1);
}
复制代码
最后我们来观察一下结果:两个集合各自独立,谁修改都不会互相影响对象
另一种快速copy集合的写法
现在很多人都用jdk8以上的版本了,那么上面这种复制集合的写法就显得有点臃肿了,可以使用java lambda表达式来进行语义上的优化,如下所示:
关注+点赞?收藏❤️不迷路
文章每周持续更新,可以微信搜索「 十分钟学编程 」第一时间阅读和催更,如果这个文章写得还不错,觉得有点东西的话
各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END