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;
}
相关推荐
为了得到深拷贝,即完全独立的副本,你需要手动实现深度复制逻辑,例如,遍历引用类型字段并逐个复制每个元素。 总之,`clone()`方法在Java中提供了对对象复制的基本支持,尤其适用于需要创建对象副本的情况。然而...
实现该接口并重写`Clone()`方法,可以选择执行浅复制或深复制。 4. **`System.Collections.Generic.Dictionary, TValue>`映射** - 当需要将一个对象映射到另一个具有相似结构的对象时,可以使用`Dictionary`类。将...
为了解决这个问题,可以使用序列化和反序列化的方法实现深复制,或者使用第三方库如Apache Commons Lang的`SerializationUtils.clone()`方法。 另外,提到“实现java类之间的多对多联系”,在Java中,多对多关系...
题目 "克隆图(python map+dfs)1" 涉及到的主要知识点是图的深拷贝,这里采用深度优先搜索(DFS)算法来实现。在Python编程中,图通常通过邻接列表来表示,而这个题目要求我们创建一个图的完全复制,即克隆图。 ...
:`三元运算符以及`map`函数来根据条件和数组动态渲染组件。 7. **Props透传**: 理解如何通过props将数据从父组件传递到子组件。 8. **React Router**: 如果涉及多页面应用,你可能会学习如何使用React Router进行...
使用`JSON.stringify`和`JSON.parse`可以实现对象的深拷贝,但它有几个局限性:无法拷贝函数,无法处理非序列化的数据结构如`Map`、`Set`,并且不能解决循环引用的问题。例如,`JSON.stringify`在遇到循环引用时会抛...
总的来说,"vJavascript-clone"项目是一个深入学习和实践JavaScript对象深克隆技术的好资源。通过研究这个项目的源码,开发者可以增强对JavaScript的理解,掌握如何在没有外部库的情况下有效地管理复杂的数据结构,...
4. **处理特殊类型**:ig_clone还需要处理Date、RegExp等特殊类型的对象,以及Map、Set等ES6新增的数据结构,确保它们能被正确克隆。 5. **返回克隆对象**:完成所有属性的复制后,返回新的克隆对象。 在实际开发中...
- 实现`clone()`方法,通常需要调用`super.clone()`,但在某些情况下,可能需要更复杂的深拷贝逻辑。 - 当需要创建新对象时,客户端直接调用已有对象的`clone()`方法,得到的新对象与原对象相同,但内存地址不同。 ...
在ES6中,Map和WeakMap可以用来创建深拷贝。这种方法对于处理类实例和原型链上的属性特别有用: ```javascript function deepCopy(obj, map = new WeakMap()) { if (obj instanceof Map) return new Map([...obj....
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...
`Map`接口则用于存储键值对,`HashMap`和`WeakHashMap`是其常见实现,`Hashtable`是线程安全的`Map`实现。 总的来说,理解并正确使用Java对象复制机制对于编写健壮的代码至关重要,尤其是在处理复杂数据结构和多...
在JavaScript中,深拷贝(Deep Clone)是一种创建对象副本的方法,它不仅复制对象的引用,还会递归地复制对象内部的所有属性和子对象。在处理复杂的数据结构时,深拷贝尤其重要,因为它可以确保原始对象和副本之间...
在JavaScript编程中,“深克隆”是一个非常重要的概念,特别是在处理复杂对象和数据结构时。深克隆是指创建一个原始对象的完整副本,包括所有嵌套的对象和数组,且副本与原始对象之间没有任何引用关系。这意味着对...
return obj.map(item => deepClone(item)); } let cloneObj = new obj.constructor(); for (let key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key]); } } return cloneObj...
return arr.map(item => Array.isArray(item) ? deepCopyArray(item) : item); } function deepCopyObject(obj) { let clone = {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { clone[key] = ...
例如,`list.stream().map(Object::clone).collect(Collectors.toUnmodifiableList())`。 3. 手动创建新的列表并遍历原始列表,对于每个元素都创建一个深拷贝并添加到新列表中。这种方法适用于没有`clone()`方法...
你可能需要了解基本的Git命令,如git clone、git add、git commit和git push。 最后,"beeplex-map"可能会教你如何通过编写脚本或使用特定的API扩展其功能。这可能涉及函数调用、参数传递和面向对象编程,以实现更...
1. 对于特殊类型的对象,如Date、RegExp、Map、Set等,上述方法可能无法正确拷贝。需要特别处理这些类型。 2. 深拷贝不能处理函数和循环引用,因为它们不适合复制。 3. 如果对象中有Symbol类型的键,需要确保在遍...
JavaScript中的深拷贝(Deep Clone)是编程中一个重要的概念,尤其在处理复杂的数据结构时。深拷贝意味着创建一个全新的对象,这个新对象包含了原对象的所有属性和子对象,而且这些属性和子对象也是独立的,修改新...