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): ①对于数据类型是 ...
随机推荐
- c#字符显示转换{0:d}
C#:String.Format数字格式化输出 : int a = 12345678; //格式为sring输出// Label1.Text = string.Format("asdfads ...
- struts---JSP界面验证码生成与验证
之前想做一个随机验证码的功能,自己也搜索了一下别人写的代码,然后自己重新用struts2实现了一下,现在将我自己实现代码贴出来!大家有什么意见都可以指出来! 首先是生成随机验证码图片的action: ...
- Windows Phone 二十、陀螺仪
API 示例 // 获取陀螺仪传感器监听对象 Gyrometer gyrometer = Gyrometer.GetDefault(); if (gyrometer == null) { await ...
- $.ajx的用法
$.ajax({type:'post',//可选geturl:'action.php',//这里是接收数据的PHP程序data:'data='dsa'',//传给PHP的数据,多个参数用&连接 ...
- Asp.net MVC5 框架揭秘 S412 实例解析 – 绝妙的扩展 模式的胜利
Asp.net MVC5 框架是个 开源的,处处可扩展的框架. 蒋先生 在他的这本书里 对如何理解框架,如何扩展框架, 给出了大量的说明和实例. 先上效果图 大部分做传统BS 的同学看到这个页面,脑海 ...
- webapi返回json格式优化
一.设置webapi返回json格式 在App_Start下的WebApiConfig的注册函数Register中添加下面这代码 config.Formatters.Remove(config.For ...
- Prime Time使用
PrimeTime一般用作sign off的timing check,也可用在DC之后的netlist的timing analysis 一般的使用流程: 1) Read design data,--- ...
- Oracle sql语句执行顺序
sql语法的分析是从右到左 一.sql语句的执行步骤: 1)词法分析,词法分析阶段是编译过程的第一个阶段.这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构 ...
- java 创建string对象机制 字符串缓冲池 字符串拼接机制
对于创建String对象的机制,在这一过程中涉及的东西还是值得探究一番的. 首先看通过new String对象和直接赋值的方式有什么区别,看如下代码: public static void main( ...
- Centos7下用命令同步标准时间
新装的CentO7S系统服务器可能设置了错误的时间,需要调整时区和时间.如下是CentOS7系统使用NTP协议,从一个时间服务器同步标准时间: [root@localhost ~]# cp /usr/ ...