Map深克隆与浅克隆问题

1 篇文章 0 订阅
1 篇文章 0 订阅

对元素是map的list进行深拷贝

1)先准备一个list,装有两个map,map的键值是基本数据类型

 List list=new ArrayList<Map<String,String>>();
		 HashMap<String, String> map=new HashMap<String, String>();
		 map.put("1", "one");
		 map.put("2", "two");
		 map.put("3", "three");
		 map.put("4", "four");
		 map.put("5", "five");
		 map.put("6", "six");
		 map.put("7", "seven");
		 map.put("8", "eight");
		 map.put("9", "nine");
		 map.put("10", "ten");
		 list.add(map);
		 HashMap<String, String> mapn=new HashMap<String, String>();
		 mapn.put("11", "one");
		 mapn.put("12", "two");
		 mapn.put("13", "three");
		 mapn.put("14", "four");
		 mapn.put("15", "five");
		 mapn.put("16", "six");
		 mapn.put("17", "seven");
		 mapn.put("18", "eight");
		 mapn.put("19", "nine");
		 mapn.put("20", "ten");
		 list.add(mapn);

方式一:

 System.out.println("-----------------第1种方式(keySet遍历拷贝map基础类型)----------------------");
		 List list1=new ArrayList<Map<String,String>>();
		 for(int i=0;i<list.size();i++) {
			 HashMap<String, String> map1=new HashMap<String, String>();
			 HashMap<String, String> tmpMap=(HashMap<String, String>) list.get(i);
			 for(String key: tmpMap.keySet()) {
				 map1.put(key, tmpMap.get(key));
			 }
			 list1.add(map1);
		 }
		 ((Map<String, String>) list.get(0)).put("1","newOne");
		 System.out.println(list);
		 System.out.println(list1);

方式二:

 System.out.println("-----------------第2种方式(entrySet遍历拷贝map基础类型)-----------------------");
		 List list2=new ArrayList<Map<String,String>>();
		 for(int i=0;i<list.size();i++) {
			 HashMap<String, String> map1=new HashMap<String, String>();
			 HashMap<String, String> tmpMap=(HashMap<String, String>) list.get(i);
			 for(Map.Entry<String, String> entry: tmpMap.entrySet()) {
				 map1.put(entry.getKey(), entry.getValue());
			 }
			 list2.add(map1);
		 }
		 ((Map<String, String>) list.get(0)).put("2","newTwo");
		 System.out.println(list);
		 System.out.println(list2);

方式三:

 System.out.println("--------------------第三种方式(map对基本类型是深复制)---------------------");
		 List list3=new ArrayList<Map<String,String>>();
		 for(int i=0;i<list.size();i++) {
			 HashMap<String, String> tmpMap=(HashMap<String, String>) list.get(i);
//			 HashMap<String, String> map1=new HashMap<String, String>(tmpMap); 这个也可以
			 HashMap<String, String> map1=(HashMap<String, String>) tmpMap.clone();
			 list3.add(map1);
		 }
		 ((Map<String, String>) list.get(0)).put("3","newThree");
		 System.out.println(list);
		 System.out.println(list3);

以上三种方式实则是一样的,区别就在于遍历或者复制map的方式不同。这里之所以加一个list套在外面,只是顺便提醒,list是引用类型,要深拷贝必须new 新的list.
由于map中存的是基本类型,所以上面三种方式都相当于进行了深复制。允许结果:
在这里插入图片描述

那么如果map中存的是引用类型,如何深复制

如果还采用上面的方式的话:

 System.out.println("--------------------第4种方式(map对引用类型是浅复制)---------------------");
		 HashMap<String, Object> hashMap = new HashMap<>();
	     List<String> list4 = new ArrayList<>();
	     list4.add("math");
	     hashMap.put("list", list4);
	     Map<String, Object> mapCopy = new HashMap<>(); // 这里可以使用Map作为父类引用
	     mapCopy = (Map<String, Object>) hashMap.clone();
	     System.out.println(mapCopy);// {list=[math]}
	     list4.add("english");
	     System.out.println(mapCopy);// {list=[math]}

现在map中存的是list也就是一个引用类型了,采用前面的方法的话,结果:
在这里插入图片描述
看吧,发现改变原来的对象值,新的也会跟着改变。这也就是浅复制了。然后你也许会怀疑是clone方法的问题,认为如果遍历map赋值就不会,那么看下面:

  System.out.println("--------------------第5种方式(map对引用类型是浅复制--getkey方式)---------------------");
	      HashMap<String, Object> hashMap5 = new HashMap<>();
		  List<String> list5 = new ArrayList<>();
		  list5.add("math");
		  hashMap5.put("list", list5);
		  Map<String, Object> mapCopy5 = new HashMap<>(); // 这里可以使用Map作为父类引用
		  for(String key :hashMap5.keySet()) {
		  	mapCopy5.put(key, hashMap5.get(key));
		  }
		 System.out.println(mapCopy5);// {list=[math]}
		 list5.add("english");
		 System.out.println(mapCopy5);

运行结果:
在这里插入图片描述如你所见,依然是浅复制。

那按照正常解决思路,当然就是想把map的value值也new 一个新的,就可以解决map的value值其实指向的是同一个地址的问题。解决办法:

 System.out.println("--------------------第6种方式(map对引用类型进行深拷贝)---------------------");
		 HashMap<String, Object> hashMap6 = new HashMap<>();
	     List<String> list6 = new ArrayList<>();
	     list6.add("math");
	     hashMap6.put("list", list6);
	     Map<String, Object> mapCopy6 = new HashMap<>(); // 这里可以使用Map作为父类引用
	     for(String key :hashMap6.keySet()) {
	    	 List<String> listtmp = new ArrayList<>((List<String>) hashMap6.get(key));
	     	mapCopy6.put(key, listtmp);
	     }
	     System.out.println(mapCopy6);// {list=[math]}
	     list6.add("english");
	     System.out.println(mapCopy6);//{list=[math]}

结果:
在这里插入图片描述上面这一种不失为一种解决办法,但是还有一种使用起来比较简单的方法,就是利用序列化实现对象的深拷贝。

 System.out.println("--------------------第7种方式(使用序列化的方式来实现对象的深拷贝)---------------------");
		// 注意不能使用Map<String, Object> map = newHashMap<>();不然CloneUtil.clone()方法报错,因为Map本身没有实现Serializable接口
	    HashMap<String, Object> hashMap7 = new HashMap<>();
	    List<String> list7 = new ArrayList<>();
	    list7.add("math");
	    hashMap7.put("list", list7);
	    Map<String, Object> mapCopy7 = new HashMap<>(); // 这里可以使用Map作为父类引用
	    mapCopy7 = CloneUtil.clone(hashMap7);
	    System.out.println(mapCopy7);// {list=[math]}
	    list7.add("english");
	    System.out.println(mapCopy7);// {list=[math]}

在这里插入图片描述
其中的工具类,可以创建一个,以后一劳永逸,源码如下:

public class CloneUtil {
	@SuppressWarnings("unchecked")
	public static <T extends Serializable> T clone(T obj) {
		T cloneObj = 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);
			cloneObj = (T) ois.readObject();
			ois.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return cloneObj;
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值