原博文:http://blog.csdn.net/qq_29329775/article/details/49516247

最近在做算法作业时出现了错误,原因是没有弄清楚java集合的深度复制和浅度复制的区别。

1.首先是对Java集合对象得浅复制与深度复制的理解

普通的集合复制只是将内存中栈的地址快拷贝一份,使得一个新的集合对象指向这个地址块,但是集合中的对象变量却是指向堆中的同一块区域。所以当拷贝的集合修改了集合对象内的数据,那么源集合对象也就随之改变了,这样的效果我们称之为Java集合对象的浅复制,即只是在栈中拷贝了,而堆中的数据并没有拷贝。而深度复制则是同时在栈中和堆中的数据进行拷贝,这样,其拷贝的集合和被拷贝的集合已经没有任何关系了。

2.一个例子

新建一个Demo类

 public class Demo {  

     private int  demoValue;  

     public void setDemoValue(int value){
this.demoValue = value;
} public int getDemoValue(){
return this.demoValue;
} public Demo(){ } public Demo(int demoValue){
this.demoValue = demoValue;
}
}

接下来,我们试验一下浅复制:

     @Test
public void testCommonCopy() { // Here I create a source collection.
ArrayList<Demo> sourceCollection = new ArrayList<Demo>(); // Here I add some objects to sourceCollection.
sourceCollection.add(new Demo(1));
sourceCollection.add(new Demo(2)); // Here I create a new empty collection.
ArrayList<Demo> newCollection = new ArrayList<Demo>();
newCollection.addAll(sourceCollection); // Now I modify some objects in new collection.
newCollection.get(0).setDemoValue(3); // Now We verify what it is inside the source collection.
for(Demo demo : sourceCollection){
System.out.println(demo.getDemoValue());
} // Now I verify if the source Collection is modified.
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);
}

最后我们来观察一下结果:搞定

接下来我们来分析一下出现这个现象的原因:

深度复制:如图:A中具有X1,X2,X3...Xn的数据,深度复制则对其每个堆和栈中的数据都进行一次拷贝,生成对应的Y1,Y2,Y3以及B对象。此时,A与B已经分别存放在不同的地址单元,所以A中改了数据,B中的数据不变,反之亦然。
浅复制:如图:A复制成B,但是A和B中的数据均指向同一个X1,X2,X3...Xn,所以当A通过某种方法改变了数据,对于B来说,其中的数据也改变了。

原文博客:http://blog.csdn.net/qq_29329775/article/details/49516247

转载---Java集合对象的深度复制与普通复制的更多相关文章

  1. [转载] Java集合---HashMap源码剖析

    转载自http://www.cnblogs.com/ITtangtang/p/3948406.html 一.HashMap概述 HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射 ...

  2. [转载] Java集合框架之小结

    转载自http://jiangzhengjun.iteye.com/blog/553191 1.Java容器类库的简化图,下面是集合类库更加完备的图.包括抽象类和遗留构件(不包括Queue的实现): ...

  3. [转载]Java集合容器简介

    Java集合容器主要有以下几类: 1,内置容器:数组 2,list容器:Vetor,Stack,ArrayList,LinkedList, CopyOnWriteArrayList(1.5),Attr ...

  4. java集合对象区别二

    集合包是Java中最常用的包,它最常用的有Collection和Map两个接口的实现类,Collection用于存放多个单对象,Map用于存放Key-Value形式的键值对. Collection中常 ...

  5. Java集合容器的深度理解

    Java容器里有很多写好的容器API,这使我们很方便的可以存储.操作我们的数据. 下面是我写的容器的特点,一些容器的不同之处,从底层源码解析一下容器实现原理 一.常用的容器目录 上图可以看出,java ...

  6. [转载]Java集合框架的常见面试题

    http://www.jfox.info/40-ge-java-ji-he-lei-mian-shi-ti-he-da-an 整理自上面链接: Java集合框架为Java编程语言的基础,也是Java面 ...

  7. [转载]Java集合系列大全总结

    Java 集合系列目录(Category) 22:06:49 2019-02-27

  8. java集合对象实现原理

    1.集合包 集合包是java中最常用的包,它主要包括Collection和Map两类接口的实现. 对于Collection的实现类需要重点掌握以下几点: 1)Collection用什么数据结构实现? ...

  9. Java集合对象比对

    1. 场景描述 通过java代码从外围接口中获取数据并落地,已经存在的不落地,不存在的落地,因有部分字段变化是正常的,只需比对3个字段相同即为相同. 2. 解决方案 设置定时任务(三个标签完成spri ...

随机推荐

  1. 定时往oracle插入数据

    1创建存储过程 create or replace procedure job_proc isbegininsert into yy (yid) values (sysdate);end; 2创建jo ...

  2. EBS R12.2 创建应用层的启动和关闭脚本

    Create the following files to start and stop R12. application tier. Change the apps and weblogic pas ...

  3. 产品Backlog

    产品BACKLOG ID Name Imp Est How to demo Notes 1 界面(首页.订单.资料) 50 2 进入界面,选择需要的界面 使用分栏界面 2 首页里的功能按钮 40 6 ...

  4. bzoj1741 [Usaco2005 nov]Asteroids 穿越小行星群

    网络流,对于每一个行星,将行星所在行到行星连一条流量为1的边,将行星到其所在列连一条流量为1的边,从源点到所有行连一条流量为1的边,将所有列到汇点都连一条流量为1的边,最大流即为答案. 代码 #inc ...

  5. Java enum(枚举)的用法详解(转)

    用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. p ...

  6. smarty中增加类似foreach的功能自动加载数据方法

    第一步:在Smarty_Compiler.class.php的_compile_tag函数中增加: 复制代码 代码如下: //加载数据的开始标签case 'load': $this->_push ...

  7. C#写WPF程序,SQLSever2008 提示插入数据成功,却查询不到数据

    1.提示存储成功,但是数据库中没有数据.今天在用C#写一个wpf程序时,要向数据库Sql server2008 中插入数据,程序提示成功,但打开数据库却没有值; 经过查询发现,数据存储到默认路径下的数 ...

  8. 2015弱校联盟(2) - J. Usoperanto

    J. Usoperanto Time Limit: 8000ms Memory Limit: 256000KB Usoperanto is an artificial spoken language ...

  9. linux 循环处理文件夹下所有文件脚本

    #!/bin/bashfunction ergodic(){ for file in ` ls $1 ` do if [ -d $1"/"$file ] then ergodic ...

  10. jQuery validation学习(2)验证身份证

    验证邮编 jQuery.validator.addMethod("isZipCode", function(value, element) { -]{}$/; return thi ...