`

Map深clone

 
阅读更多

Map深clone  

 

 

       近来看到很多的关于Map深克隆的文章,可谓是良莠不齐; 有的文章分析的比较好,但是给出的例子却不对。在我所看的文章的例子几乎都用String类作为演示例子。测试出来的结果貌似是对了,但是这个结果却蒙蔽了大家,就连原文作者也没有发现。值得注意的是:String这个类是非常特殊!从API中可以看到类的声明:public final class String ;注意是final修饰的,改变它的值,实则它的引用地址也发生了改变,下面我们看一下例子:
①String aStr = "a";
②String bStr = "a";
③bStr = "c";
当程序执行完①时,内存中将保存“a”并将aStr指向这个内存地址;但执行到②时,注意,此时并没有开辟新的内存,而是将bStr直接指向“a”;因此aStr与bStr一定是完全相等的(注意,是完全相等;这个例子也可以区分‘equals’与‘==’的区别。)但程序执行到③时,内存就重新开辟空间保存“c” 此时bStr就指向“c”的内存地址。我们输出bStr确实看到bStr发生了改变,但是并没有改变原来bStr所指地址的那个值,也就是说并没有将“a”改成“c”,而是将bStr直接指向另一个引用地址,因此我们往往误以为bStr的‘值(地址和值)’改变了。 不打算继续说了,估计大家被绕晕了。简而言之就是:你一旦改变了String的值就意味着它所指向的内存地址也就发生了变化(这个原理同样也可以解释声明String类型变量时建议直接用“=String”而不是用“=new String()”的方式声明,以及String类型变量不要用累加次数过多(一般是3次或3次以下))。所以那些文章用String做演示是犯了一个非常低级的错误!  若用其它的类(比如自定义的JavaBean)代替String的话你就发现,其实任然还只是浅克隆,而大费周章的所重写的clone方法然与Object里面继承过来的方法结果仍然相同,可谓是白费了一番心思!
 下面本人写的一个Map深克隆的例子,仍然是通过重写clone方法来实现的,供给大家参考使用:

JAVABean , Map格式:Map<String,User>

/**

* @author TDW
*
*/

publicclassUser  implementsSerializable{
 privatestaticfinallong serialVersionUID =1L;
 privateString id;
 privateString userName;
 privateString password;
 privateString nickName;
 privateString[] hobby;

//get、set method 略

}

deep clone test :

package com.study.demo.clone;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.study.api.bean.User;

/**
 * Map deep clone test
 * @author TDW
 *
 */
publicclassMapCloneTest{
 class customHashMap extendsHashMap<Object,Object>{
  privatestaticfinallong serialVersionUID =1L;

  public customHashMap(){
   super();
  }

  public customHashMap(int initialCapacity){
   super(initialCapacity);
  }

  publicObject clone(){
   Map<Object,Object> target =newHashMap<Object,Object>();
   try{
    ByteArrayOutputStream byteout =null;
    ObjectOutputStreamout=null;
    Object obj =null;
    for(Iterator<Object> keyIt =this.keySet().iterator(); keyIt
      .hasNext();){
     Object key = keyIt.next();
     byteout =newByteArrayOutputStream();
     out=newObjectOutputStream(byteout);
     out.writeObject(this.get(key));
     ByteArrayInputStream bytein =newByteArrayInputStream(
       byteout.toByteArray());
     ObjectInputStreamin=newObjectInputStream(bytein);
     obj =in.readObject();// 反序列化出来,就相当于将原来的值和地址(即引用)copy了一份
     target.put(key, obj);// 习惯上一般key是不做修改的,因此没有copy key的必要
           // ,倘若有必要则同样反序列化出来就行了(如果是String类型也无需反序列化,上面已经解释的很清楚了)
    }
   } catch(Exception e){
    e.printStackTrace();
   }
   return target;
  }
 }

 publicstaticvoid main(String[] args){
  User user1 =newUser();
  user1.setId("11111111111111");
  User user2 =newUser();
  user2.setId("22222222222222");
  customHashMap source =(newMapCloneTest()).new customHashMap();
  source.put("key1", user1);
  source.put("key2", user2);

  System.out.println(source);
  Map target =(Map) source.clone();
  User user =(User) target.get("key1");
  user.setId("xxxxxxxxxxxxxx");// 改变副本的值

  System.out.println(target);// 对比结果
  System.out.println(source);// 源,没有被修改
 }

}

输出结果大家自行对比。
  不仅如此,List也可以用此方式进行深克隆,凡是实现过序列号接口的都可以通过此方式进行深克隆,下面是list深克隆例子:

/**
  * List深度clone
  * @param src
  * @return
  */
 publicstaticArrayList<Object> copyList(ArrayList<Object> src){  
  ArrayList<Object> list =null;
  try{
   ByteArrayOutputStream byteout =newByteArrayOutputStream();  
         ObjectOutputStreamout=newObjectOutputStream(byteout);  
         out.writeObject(src);
         ByteArrayInputStream bytein =newByteArrayInputStream(byteout.toByteArray());  
         ObjectInputStreamin=newObjectInputStream(bytein);  
         list =(ArrayList<Object>)in.readObject();
        }catch(Exception e){
         System.out.println("cache copy error !");
         e.printStackTrace();
        }
        return list;  
    }

 
 
分享到:
评论

相关推荐

    java clone的小例子

    为了得到深拷贝,即完全独立的副本,你需要手动实现深度复制逻辑,例如,遍历引用类型字段并逐个复制每个元素。 总之,`clone()`方法在Java中提供了对对象复制的基本支持,尤其适用于需要创建对象副本的情况。然而...

    C#Map映射各个方式性能大比拼

    实现该接口并重写`Clone()`方法,可以选择执行浅复制或深复制。 4. **`System.Collections.Generic.Dictionary, TValue&gt;`映射** - 当需要将一个对象映射到另一个具有相似结构的对象时,可以使用`Dictionary`类。将...

    java深复制浅复制的实现源代码

    为了解决这个问题,可以使用序列化和反序列化的方法实现深复制,或者使用第三方库如Apache Commons Lang的`SerializationUtils.clone()`方法。 另外,提到“实现java类之间的多对多联系”,在Java中,多对多关系...

    克隆图(python map+dfs)1

    题目 "克隆图(python map+dfs)1" 涉及到的主要知识点是图的深拷贝,这里采用深度优先搜索(DFS)算法来实现。在Python编程中,图通常通过邻接列表来表示,而这个题目要求我们创建一个图的完全复制,即克隆图。 ...

    react_clone和教程

    :`三元运算符以及`map`函数来根据条件和数组动态渲染组件。 7. **Props透传**: 理解如何通过props将数据从父组件传递到子组件。 8. **React Router**: 如果涉及多页面应用,你可能会学习如何使用React Router进行...

    12-深拷贝.md

    使用`JSON.stringify`和`JSON.parse`可以实现对象的深拷贝,但它有几个局限性:无法拷贝函数,无法处理非序列化的数据结构如`Map`、`Set`,并且不能解决循环引用的问题。例如,`JSON.stringify`在遇到循环引用时会抛...

    vJavascript-clone:香草Javascript研究

    总的来说,"vJavascript-clone"项目是一个深入学习和实践JavaScript对象深克隆技术的好资源。通过研究这个项目的源码,开发者可以增强对JavaScript的理解,掌握如何在没有外部库的情况下有效地管理复杂的数据结构,...

    ig_clone

    4. **处理特殊类型**:ig_clone还需要处理Date、RegExp等特殊类型的对象,以及Map、Set等ES6新增的数据结构,确保它们能被正确克隆。 5. **返回克隆对象**:完成所有属性的复制后,返回新的克隆对象。 在实际开发中...

    详解JAVA 原型模式

    - 实现`clone()`方法,通常需要调用`super.clone()`,但在某些情况下,可能需要更复杂的深拷贝逻辑。 - 当需要创建新对象时,客户端直接调用已有对象的`clone()`方法,得到的新对象与原对象相同,但内存地址不同。 ...

    js代码-深拷贝实现

    在ES6中,Map和WeakMap可以用来创建深拷贝。这种方法对于处理类实例和原型链上的属性特别有用: ```javascript function deepCopy(obj, map = new WeakMap()) { if (obj instanceof Map) return new Map([...obj....

    arcgis engine 控件设置

    miniMap.Document = mapCtrl.Map.Document.Clone() as MapDocument; MiniMap miniMapCtrl = new MiniMap(); miniMapCtrl.Map = miniMap; private void mapCtrl_AfterDraw(object sender, DrawEventArgs e) { if (e...

    java对象复制

    `Map`接口则用于存储键值对,`HashMap`和`WeakHashMap`是其常见实现,`Hashtable`是线程安全的`Map`实现。 总的来说,理解并正确使用Java对象复制机制对于编写健壮的代码至关重要,尤其是在处理复杂数据结构和多...

    js代码-深拷贝deepClone

    在JavaScript中,深拷贝(Deep Clone)是一种创建对象副本的方法,它不仅复制对象的引用,还会递归地复制对象内部的所有属性和子对象。在处理复杂的数据结构时,深拷贝尤其重要,因为它可以确保原始对象和副本之间...

    深克隆

    在JavaScript编程中,“深克隆”是一个非常重要的概念,特别是在处理复杂对象和数据结构时。深克隆是指创建一个原始对象的完整副本,包括所有嵌套的对象和数组,且副本与原始对象之间没有任何引用关系。这意味着对...

    hh99_clone:Voyage 99第4章克隆编码

    return obj.map(item =&gt; deepClone(item)); } let cloneObj = new obj.constructor(); for (let key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key]); } } return cloneObj...

    js代码-实现一个基本的深拷贝

    return arr.map(item =&gt; Array.isArray(item) ? deepCopyArray(item) : item); } function deepCopyObject(obj) { let clone = {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { clone[key] = ...

    U10316044_HW5_15_10:(修改MyStack类)重写代码清单11.10中的MyStack类来执行列表字段的深拷贝

    例如,`list.stream().map(Object::clone).collect(Collectors.toUnmodifiableList())`。 3. 手动创建新的列表并遍历原始列表,对于每个元素都创建一个深拷贝并添加到新列表中。这种方法适用于没有`clone()`方法...

    beeplex-map

    你可能需要了解基本的Git命令,如git clone、git add、git commit和git push。 最后,"beeplex-map"可能会教你如何通过编写脚本或使用特定的API扩展其功能。这可能涉及函数调用、参数传递和面向对象编程,以实现更...

    js代码-深度/广度优先遍历实现对象的深度拷贝

    1. 对于特殊类型的对象,如Date、RegExp、Map、Set等,上述方法可能无法正确拷贝。需要特别处理这些类型。 2. 深拷贝不能处理函数和循环引用,因为它们不适合复制。 3. 如果对象中有Symbol类型的键,需要确保在遍...

    javascript深拷贝(deepClone)详解

    JavaScript中的深拷贝(Deep Clone)是编程中一个重要的概念,尤其在处理复杂的数据结构时。深拷贝意味着创建一个全新的对象,这个新对象包含了原对象的所有属性和子对象,而且这些属性和子对象也是独立的,修改新...

Global site tag (gtag.js) - Google Analytics