Map深克隆与浅克隆问题

直接上代码

public class MapTest {
	// 浅复制:只复制对象的引用,两个引用仍然指向同一个对象,在内存中占用同一块内存
	@Test
	public void test1() {
		Map map = new HashMap();
		map.put("num1", 100);
		// map中数据改变,mapCopy数据也会改变
		Map mapCopy = map;
		System.out.println(mapCopy); // {num1=100}
		map.put("num1", 200);
		System.out.println(mapCopy); // {num1=200}
		// 同样改变mapCopy中数据,map中数据也会改变
		mapCopy.put("num1", 300);
		System.out.println(map); // {num1=300}
	}

	// 演示向list中添加map被覆盖的问题
	@Test
	public void test2() {
		List> list = new ArrayList<>();
		// map并没有改变过引用,所以map指向的对象一直是同一个,导致list数据全被覆盖
		Map map = new HashMap<>();
		for (int i = 0; i < 2; i++) {
			map.put("num", i);
			list.add(map);
		}
		System.out.println(list); // [{num=1}, {num=1}]
	}

	// 演示针对test2的解决方法一
	@Test
	public void test3() {
		List> list = new ArrayList<>();
		Map map;
		for (int i = 0; i < 2; i++) {
			map = new HashMap<>(); // 每次循环,创建一个新map对象
			map.put("num", i);
			list.add(map);
		}
		System.out.println(list); // [{num=0}, {num=1}]

	}

	// HashMap的putAll()方法: 只对于基本类型是深复制!
	@Test
	public void test4() {
		Map map = new HashMap<>();
		map.put("name", "zhangsan");
		Map mapCopy = new HashMap<>();
		mapCopy.putAll(map);
		System.out.println(mapCopy);// {name=zhangsan}
		map.put("name", "lisi");
		System.out.println(mapCopy);// {name=zhangsan}

	}

	// HashMap的putAll()方法:对于引用类型是浅复制!!!!!!!!!!!
	@Test
	public void test5() {
		Map map = new HashMap<>();
		List list = new ArrayList<>();
		list.add("math");
		map.put("list", list);
		Map mapCopy = new HashMap<>();
		mapCopy.putAll(map);
		System.out.println(mapCopy);// {list=[math]}
		list.add("english");
		System.out.println(mapCopy);// {list=[math, english]}
	}

	// 使用序列化的方式来实现对象的深拷贝
	@Test
	public void test6() {
		// 注意不能使用Map map = newHashMap<>();不然CloneUtil.clone()方法报错,因为Map本身没有实现Serializable接口
		HashMap hashMap = new HashMap<>();
		List list = new ArrayList<>();
		list.add("math");
		hashMap.put("list", list);
		Map mapCopy = new HashMap<>(); // 这里可以使用Map作为父类引用
		mapCopy = CloneUtil.clone(hashMap);
		System.out.println(mapCopy);// {list=[math]}
		list.add("english");
		System.out.println(mapCopy);// {list=[math]}
	}
}
/**
  * 使用序列化来实现对象的深拷贝(对象必须是实现了 Serializable接口)
 * Map本身没有实现 Serializable 接口,所以这种方式不能序列化Map,也就是不能深拷贝Map。但是HashMap是可以的。
 * @author chenzg
 * @date 2019年8月21日 下午5:05:51
 */
public class CloneUtil {
	@SuppressWarnings("unchecked")
	public static  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;
	}
}

你可能感兴趣的:(各种问题)