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

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

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

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

2.一个例子

新建一个Demo类

  1. public class Demo {
  2.  
  3. private int demoValue;
  4.  
  5. public void setDemoValue(int value){
  6. this.demoValue = value;
  7. }
  8.  
  9. public int getDemoValue(){
  10. return this.demoValue;
  11. }
  12.  
  13. public Demo(){
  14.  
  15. }
  16.  
  17. public Demo(int demoValue){
  18. this.demoValue = demoValue;
  19. }
  20. }

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

  1. @Test
  2. public void testCommonCopy() {
  3.  
  4. // Here I create a source collection.
  5. ArrayList<Demo> sourceCollection = new ArrayList<Demo>();
  6.  
  7. // Here I add some objects to sourceCollection.
  8. sourceCollection.add(new Demo(1));
  9. sourceCollection.add(new Demo(2));
  10.  
  11. // Here I create a new empty collection.
  12. ArrayList<Demo> newCollection = new ArrayList<Demo>();
  13. newCollection.addAll(sourceCollection);
  14.  
  15. // Now I modify some objects in new collection.
  16. newCollection.get(0).setDemoValue(3);
  17.  
  18. // Now We verify what it is inside the source collection.
  19. for(Demo demo : sourceCollection){
  20. System.out.println(demo.getDemoValue());
  21. }
  22.  
  23. // Now I verify if the source Collection is modified.
  24. Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1);
  25. }

对其的执行结果,很明显,newCollection中改变的Demo对象在SourceCollection中也跟着改变了,这说明两个集合中的Demo对象是同一个对象。这也是浅复制所存在的弊端。那么如何将两个集合独立开来呢,即如何进行深度复制,我们不烦继续往下阅读:

首先我们先对Demo类作一下处理,使其实现Cloneable接口,并重写它的clone方法
  1. protected Demo clone() throws CloneNotSupportedException {
  2. return (Demo)super.clone();
  3. }

然后我们来进行深度复制:

  1. @Test
  2. public void testCopyDeep() throws Exception{
  3. ArrayList<Demo> sourceCollection = new ArrayList<Demo>();
  4. sourceCollection.add(new Demo(1));
  5. sourceCollection.add(new Demo(2));
  6.  
  7. ArrayList<Demo> newCollection = new ArrayList<Demo>();
  8. for(Demo demo : sourceCollection){
  9. newCollection.add(demo.clone());
  10. }
  11. newCollection.get(0).setDemoValue(3);
  12. for(Demo demo : sourceCollection){
  13. System.out.println(demo.getDemoValue());
  14. }
  15. Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1);
  16. }

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

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

深度复制:如图: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. Web3D编程入门总结——WebGL与Three.js基础介绍

    /*在这里对这段时间学习的3D编程知识做个总结,以备再次出发.计划分成“webgl与three.js基础介绍”.“面向对象的基础3D场景框架编写”.“模型导入与简单3D游戏编写”三个部分,其他零散知识 ...

  2. RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新)

    继续上次的学习笔记,在RCNN之后是Fast RCNN,但是在Fast RCNN之前,我们先来看一个叫做SPP-net的网络架构. 一,SPP(空间金字塔池化,Spatial Pyramid Pool ...

  3. Java中的4种代码块

    一.普通代码块 直接在一个方法中出现的{}就称为普通代码块,例子程序如下: public class CodeDemo01{ public static void main(String[] args ...

  4. wex5 教程之 图文讲解 文件上传attachmentSimple(1)

    视频教程地址:http://v.youku.com/v_show/id_XMTc4NDAyMTY4OA==.html 效果预览: 1 调用attchmentSimple组件,打开文件管理器,并选中,显 ...

  5. 31、springmvc(注解)

    回顾什么是springmvc,它与spring有什么关系 springmvc属于spring框架的后续产品,用在基于MVC的表现层开发,类似于struts2框架 参见<<springmvc ...

  6. 优秀Python学习资源收集汇总(强烈推荐)

    Python是一种面向对象.直译式计算机程序设计语言.它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用縮进来定义语句块.与Scheme.Ruby.Perl ...

  7. linux初始化配置---主机名、关闭防火墙、关闭selinux

    一.修改主机名 1.零时修改 [root@localhost network-scripts]# hostname jw07 然后就可以看到我们的主机名被修改了

  8. hibernate的二级缓存

    缓存(Cache): 计算机领域非常通用的概念.它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能.缓存中的数 ...

  9. ms sql 经典语句【珍藏】

    数据库中字段中有不需要"[演示数据请勿真实购买]" 例如: update Hishop_Products set ProductName = replace(ProductName ...

  10. manacher浅析

    manacher算法的输入是一个字符串,可以计算出以每个字符为中心的最长回文子串的半径.为了避免讨论奇数偶数,将原串的每两个字母之间以及前后各加一个特殊字母,比如'#',那么对于abcbb就变成了 # ...