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): ①对于数据类型是 ...
随机推荐
- 0-js判断电脑或手机登录
<script type="text/javascript"> try{ if(/Android|webOS|iPhone|iPod|BlackBerry/i.test ...
- 与资源库同步时,我的svn报错 Previous operation has not finished; run 'cleanup' if it was interrupted
解决办法:选择你的项目,右键,小组(Team),刷新或清理(Refresh or Clean)即可.
- iOS第三方库管理工具
作者:彷徨iOS 原文地址1:http://iostree.sinaapp.com/?p=78 原文地址2:http://blog.csdn.net/wzzvictory/article/detail ...
- Centos vsftpd服务器搭建
Centos vsftpd服务器搭建 时间:2016-07-18 1.最为简单的vsftpd服务器搭建 1.安装vsftpd 1.yum 安装 yum install vsftpd 2.rpm文件安装 ...
- java 数组详解
from : http://blog.csdn.net/jionjionyoushen/article/details/6223006 1.关于数组的特点 1)在Java中,无论使用数组或集合,都有边 ...
- ArcGIS10.1 发布气温插值GP服务
首先通过ModelBuilder 工具 构建模型 然后通过模块右键 设置输入参数 或者直接将一个模块设为输入参数 在输出模块的右键属性上 可以设置lyr文件用于渲染 设置数据添加到显示用于不是发布的时 ...
- Xcode Build Settings Architectures
http://foggry.com/blog/2014/05/09/xcodeshe-zhi-xiang-zhi-architectureshe-valid-architectures/ https: ...
- jquery实现前台倒计时。应用下单24小时后自动取消该订单
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- easyui DataGrid 工具类之 util js
var jq; var tab; var tabsIndex; /** ...
- 微信支付:curl出错,错误码:60
如下是运行微信支付测试代码时出错代码: Fatal error: Uncaught exception ‘WxPayException‘ with message ‘curl出错,错误码:60‘ in ...