【Collection】Map浅复制与深复制
程序员文章站
2022-05-23 14:18:12
...
一、浅复制 (=)
public static void testDeepClone1(){
Map<Integer,Integer> map1 = new HashMap<>();
map1.put(1,1);
map1.put(2,2);
Map<Integer,Integer> map2 = map1;
System.out.println("map1 == map2 :" + (map1 == map2));
map2.remove(1);
System.out.println("map1 :" + map1);
System.out.println("map2 :" + map2);
}
- 输出:
map1 == map2 :true
map1 :{2=2}
map2 :{2=2}
- 结论:等号肯定是浅复制,直接比较俩对象 map1== map2 为true就可以知道。
二、伪深复制 (new HashMap)
public static void testDeepClone2(){
Map<Integer,Integer> map1 = new HashMap<>();
map1.put(1,1);
map1.put(2,2);
Map<Integer,Integer> map2 = new HashMap<>(map1);
System.out.println("map1 == map2 :" + (map1 == map2));
map2.remove(1);
System.out.println("map1 :" + map1);
System.out.println("map2 :" + map2);
}
- 输出:
map1 == map2 :false
map1 :{1=1, 2=2}
map2 :{2=2}
- 结论:不相等了,确实不是同一个对象,map1与map2也不相互影响。咋一看没毛病。但是其实还不是深复制,继续往下看。
三、解密伪深复制 (new HashMap)
注意:value是一个集合set,也就是一个对象
public static void testDeepClone3(){
Map<Integer, Set<Integer>> map1 = new HashMap<>();
map1.put(1, Sets.newHashSet(11,12,13));
map1.put(2, Sets.newHashSet(21,22,23));
Map<Integer, Set<Integer>> map2 = new HashMap<>(map1);
System.out.println("map1 == map2 :" + (map1 == map2));
System.out.println("map1.get(1) == map2.get(1) :" + (map1.get(1) == map2.get(1)));
// remove掉集合里面的一个元素
map2.get(1).remove(11);
System.out.println("map1 :" + map1);
System.out.println("map2 :" + map2);
}
- 输出:
map1 == map2 :false
map1.get(1) == map2.get(1) :true
map1 :{1=[12, 13], 2=[21, 22, 23]}
map2 :{1=[12, 13], 2=[21, 22, 23]}
-
结论:看到最关键的没有!map1.get(1) == map2.get(1) :true ,也就是new HashMap()这个小伙子捅得不够深,是假的深复制。
-
自行温习“值传递”与“引用传递”
四、真正的深复制
- 采用序列化的方式,对象转成二进制流,再从二进制流转成对象。
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj) {
T clonedObj = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
clonedObj = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return clonedObj;
}
public static void testDeepClone4(){
HashMap<Integer, Set<Integer>> map1 = new HashMap<>();
map1.put(1, Sets.newHashSet(11,12,13));
map1.put(2, Sets.newHashSet(21,22,23));
Map<Integer, Set<Integer>> map2 = clone(map1);
System.out.println("map1 == map2 :" + (map1 == map2));
System.out.println("map1.get(1) == map2.get(1) :" + (map1.get(1) == map2.get(1)));
// remove掉集合里面的一个元素
map2.get(1).remove(11);
System.out.println("map1 :" + map1);
System.out.println("map2 :" + map2);
}
- 输出:
map1 == map2 :false
map1.get(1) == map2.get(1) :false
map1 :{1=[12, 13, 11], 2=[21, 22, 23]}
map2 :{1=[12, 13], 2=[21, 22, 23]}
- 结论:采用二进制流,可以实现真正的深复制!!!但是还没完,下面继续说
五、更高性能的深复制
- 引入pom ,可以去 maven repository搜索最新版本
- Cloner.standard().deepClone(map1)
<dependency>
<groupId>uk.com.robust-it</groupId>
<artifactId>cloning</artifactId>
<version>1.9.3</version>
</dependency>
- 代码
public static void testDeepClone5(){
HashMap<Integer, Set<Integer>> map1 = new HashMap<>();
map1.put(1, Sets.newHashSet(11,12,13));
map1.put(2, Sets.newHashSet(21,22,23));
Map<Integer, Set<Integer>> map2 = Cloner.standard().deepClone(map1);
System.out.println("map1 == map2 :" + (map1 == map2));
System.out.println("map1.get(1) == map2.get(1) :" + (map1.get(1) == map2.get(1)));
// remove掉集合里面的一个元素
map2.get(1).remove(11);
System.out.println("map1 :" + map1);
System.out.println("map2 :" + map2);
}
- 输出:
map1 == map2 :false
map1.get(1) == map2.get(1) :false
map1 :{1=[12, 13, 11], 2=[21, 22, 23]}
map2 :{1=[12, 13], 2=[21, 22, 23]}
- 同样实现深复制
六、深复制性能对比
public static void testDeepClonePerformance(){
List<Integer> list = Lists.newArrayList();
for (int i = 0; i < 10000; i++) {
list.add(i);
}
HashMap<Integer, List<Integer>> mapSource = Maps.newHashMap();
for (int i = 0; i < 10000; i++) {
mapSource.put(i,list);
}
long begin = System.currentTimeMillis();
Cloner.standard().deepClone(mapSource);
System.out.println("Cloner.standard().deepClone it costs : " + (System.currentTimeMillis() - begin) + "ms");
long begin2 = System.currentTimeMillis();
clone(mapSource);
System.out.println("io deepClone it costs : " + (System.currentTimeMillis() - begin2) + "ms");
}
- 输出:
Cloner.standard().deepClone it costs : 39ms
io deepClone it costs : 121ms
- 结论:推荐使用 Cloner.standard().deepClone
七、推荐使用 Cloner.standard().deepClone
上一篇: WebGL - 七种基本图形的绘制
下一篇: 硬件设计6---什么是滞回电路