Map拷贝 关于对象深拷贝 浅拷贝的问题
问题:map拷贝时发现数据会变化。
高能预警,你看到的下面的栗子是不正确的,后面有正确的一种办法,如果需要看的话的,请看到底,感谢各同学的提醒,已做更正,一定要看到最后
|
public class CopyMap {
/**
* @author 张仲华
* @param args
* 2014 -8 -6 上午9:29:33
*/
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<String,Integer>();
map.put( "key1", 1);
Map<String,Integer> mapFirst = map;
System. out.println( mapFirst);
map.put( "key2", 2);
System. out.println( mapFirst);
}
}
|
深复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
|
public class CopyMap {
/**
* @author 张仲华
* @param args
* 2014 -8 -6 上午9:29:33
*/
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<String,Integer>();
map.put( "key1", 1);
Map<String,Integer> mapFirst = new HashMap<String,Integer>();
mapFirst.putAll(map); //深拷贝
System. out.println(mapFirst);
map.put( "key2", 2);
System. out.println(mapFirst);
}
}
|
参考:http://blog.csdn.net/lzkkevin/article/details/6667958
注意!!!注意!!!!注意!!! 上面并不是深拷贝,留下来的原因是提醒大家,这里是存在错误的。(很高兴你看到这里了)
感谢下面这几位朋友的提醒。


文章更正如下:
如何实现Map的深拷贝呢?
有一种方法,是使用序列化的方式来实现对象的深拷贝,但是前提是,对象必须是实现了Serializable接口才可以,Map本身没有实现 Serializable 这个接口,所以这种方式不能序列化Map,也就是不能深拷贝Map。但是HashMap是可以的,因为它实现了 Serializable。下面的方式,基于HashMap来讲,非Map的拷贝。
具体实现如下:
01 |
public class CloneUtils { |
02 |
03 |
@SuppressWarnings("unchecked") |
04 |
public static <T extends Serializable> T clone(T obj){ |
05 |
|
06 |
T clonedObj = null; |
07 |
try { |
08 |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
09 |
ObjectOutputStream oos = new ObjectOutputStream(baos); |
10 |
oos.writeObject(obj); |
11 |
oos.close(); |
12 |
|
13 |
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
14 |
ObjectInputStream ois = new ObjectInputStream(bais); |
15 |
clonedObj = (T) ois.readObject(); |
16 |
ois.close(); |
17 |
|
18 |
}catch (Exception e){ |
19 |
e.printStackTrace(); |
20 |
} |
21 |
|
22 |
return clonedObj; |
23 |
} |
24 |
} |
如何使用呢,下面是个使用的例子,同时证明了Map的putAll方法并没有实现深拷贝,putAll仅对基本数据类型起到深拷贝的作用。
栗子:
01 |
public static void main(String[] args) { |
02 |
|
03 |
List<Integer> list = new ArrayList<Integer>(); |
04 |
list.add(100); |
05 |
list.add(200); |
06 |
|
07 |
HashMap<String,Object> map = new HashMap<String,Object>(); |
08 |
//放基本类型数据 |
09 |
map.put("basic", 100); |
10 |
//放对象 |
11 |
map.put("list", list); |
12 |
|
13 |
HashMap<String,Object> mapNew = new HashMap<String,Object>(); |
14 |
mapNew.putAll(map); |
15 |
|
16 |
System.out.println("----数据展示-----"); |
17 |
System.out.println(map); |
18 |
System.out.println(mapNew); |
19 |
|
20 |
System.out.println("----更改基本类型数据-----"); |
21 |
map.put("basic", 200); |
22 |
System.out.println(map); |
23 |
System.out.println(mapNew); |
24 |
|
25 |
System.out.println("----更改引用类型数据-----"); |
26 |
list.add(300); |
27 |
System.out.println(map); |
28 |
System.out.println(mapNew); |
29 |
|
30 |
|
31 |
System.out.println("----使用序列化进行深拷贝-----"); |
32 |
mapNew = CloneUtils.clone(map); |
33 |
list.add(400); |
34 |
System.out.println(map); |
35 |
System.out.println(mapNew); |
36 |
|
37 |
} |
输出结果如下:

最上面的两条是原始数据,使用了putAll方法拷贝了一个新的mapNew对象,
中间两条,是修改map对象的基本数据类型的时候,并没有影响到mapNew对象。
但是看倒数第二组,更改引用数据类型的时候,发现mapNew的值也变化了,所以putAll并没有对map产生深拷贝。
最后面是使用序列化的方式,发现,更改引用类型的数据的时候,mapNew对象并没有发生变化,所以产生了深拷贝。
上述的工具类,可以实现对象的深拷贝,不仅限于HashMap,前提是实现了Serlizeable接口。
还没有看putAll的源码实现,后面看下为什么不能实现深拷贝。
Map拷贝 关于对象深拷贝 浅拷贝的问题的更多相关文章
- Java对象深拷贝浅拷贝总结
目录 深拷贝 1. 手动new 2. clone方法 3. java自带序列化 4. json序列化 性能测试 深拷贝总结 浅拷贝 1. spring BeanUtils(Apache BeanUti ...
- ios深拷贝,浅拷贝,拷贝自定义对象的简单介绍(转)
copy语法的目的:改变副本的时候,不会影响到源对象: 深拷贝:内容拷贝,会产生新的对象.新对象计数器置为1,源对象计数器不变. 浅拷贝:指针拷贝,不会产生新的对象.源对象计数器+1. 拷贝有下面两个 ...
- Object对象的浅拷贝与深拷贝方法详解
/* ===================== 直接看代码 ===================== */ <!DOCTYPE html> <html> <head& ...
- java 将Map拷贝到另一个Map对象当中
java 将Map拷贝到另一个Map对象当中 CreateTime--2018年6月4日09点46分 Author:Marydon 1.需求说明 将一个MapA对象中所有的键值对完全拷贝到另一个M ...
- 也来玩玩 javascript对象深拷贝,浅拷贝
经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One method of copying an object is ...
- C++拷贝构造函数(深拷贝,浅拷贝)
对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #i ...
- javascript对象深拷贝,浅拷贝 ,支持数组
javascript对象深拷贝,浅拷贝 ,支持数组 经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One meth ...
- C++拷贝构造函数(深拷贝与浅拷贝)
转自http://blog.csdn.net/lwbeyond/article/details/6202256/ 一. 什么是拷贝构造函数 对于普通类型的对象来说,它们之间的复制是很简单的,例如:in ...
- Java对象的浅拷贝和深拷贝&&String类型的赋值
Java中的数据类型分为基本数据类型和引用数据类型.对于这两种数据类型,在进行赋值操作.方法传参或返回值时,会有值传递和引用(地址)传递的差别. 浅拷贝(Shallow Copy): ①对于数据类型是 ...
随机推荐
- HDU-1233 还是畅通工程
Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能 ...
- 夺命雷公狗----Git---2---基本用法
首先我们来创建一个git仓库,其实命令也是很简单的.. git init 其实在创建完成后,该目录会多了一个.git的文件夹,但该文件夹是隐藏的.... 其实这就是一个git仓库,特别建议不要在这个目 ...
- 【原创】我所理解的自动更新-外网web服务器配置
ClientDownload和ClientUpdate共享渠道配置信息: channel-0.php //以appstore的渠道为例 <?php define('APPNAME', 'TOKE ...
- hdu 3839 Ancient Messages (dfs )
题目大意:给出一幅画,找出里面的象形文字. 要你翻译这幅画,把象形文字按字典序输出. 思路:象形文字有一些特点,分别有0个圈.1个圈.2个圈...5个圈.然后dfs或者bfs,就像油井问题一样,找出在 ...
- GPS经纬度换算成XY坐标
; }
- ebs history to look for password
-bash-3.2$ ps -ef|grep tns root 101 2 0 Jun01 ? 00:00:00 [netns] oravibs 10625 1 0 Sep09 ? 00:01:03 ...
- 主机和虚拟机不能ping通问题
VMware的三种网络模式附上: 在vmw中,默认有3个虚拟交换机 分别是VMnet0(桥接).VMnet1(主机网络)以及VMnet8(NAT) 还可以根据需要添加VMnet2~VMnet7和VMn ...
- mysql共享表空间转独立表空间
使用innodb_export_import.py脚本: https://github.com/thecpaneladmin/innodb-tools 安装MySQL-python模块: shell ...
- edittext把软键盘上的回车键改为搜索、发送或者 下一步,窗口随软键盘弹出而改变。
http://m.blog.csdn.net/article/details?id=51350501 以上博文讲解很详细. 如图所示,有时候为了布局美观,在搜索时没有搜索按钮,而是调用软件盘上的按钮. ...
- python查找空格和中文
前言 图片或者文件夹下,命名不规范,有中文或者有空格.这个脚本批处理查找,并输出到 txt中方便修改,也可以扩展为 直接脚本删除空格等.目前只用在Windows上,mac没有测试,不知道能不能行,有需 ...