zoukankan      html  css  js  c++  java
  • 转载---Java集合对象的深度复制与普通复制

    原博文: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

  • 相关阅读:
    Vuex核心属性(上)
    layui 将json字符串以表格的形式展现出来
    Vue 路由懒加载 和 路由导航守卫
    jq遍历服务器发送过来的json字符串
    前端的发展
    关于定义函数的几种方式 及(箭头函数)
    js 子页面获取父页面的值
    关于数组的响应式方法和非响应式方法
    python3 -- random 模块
    多任务编程 -- multiprocessing 模块(创建多进程、进程池使用、进程间通信)
  • 原文地址:https://www.cnblogs.com/f91og/p/6081692.html
Copyright © 2011-2022 走看看