场景描述
浅拷贝与深拷贝的概念就不用赘述了,本质区别是两个引用指向同一个对象还是分别指向不同的对象。这里要讲的是 HashMap的深拷贝,如果所有的 value 是基础类型的,那简单的构造函数就能完成深拷贝。但是当 value 是引用类型时,以构造函数为代表的 ”深拷贝“ 方式就有问题了。
此时最有效的方式是使用序列化,先将本体序列化,再反序列化时会 new 出新的 Map,即便是引用嵌套了好多层,也能迅速实现深拷贝。
基于 Gson 的深拷贝实现
Gson 是个序列化/反序列化库,实现深拷贝的demo如下:
HashMap<Integer, Employee> employeeMap = new HashMap<>();
employeeMap.put(1, new Employee(1l, "Alex", LocalDate.of(1990, 01, 01)));
employeeMap.put(2, new Employee(2l, "Bob", LocalDate.of(1990, 02, 01)));
Gson gson = new Gson();
String jsonString = gson.toJson(employeeMap);
Type type = new TypeToken<HashMap<Integer, Employee>>(){}.getType();
HashMap<Integer, Employee> clonedMap = gson.fromJson(jsonString, type);
System.out.println(clonedMap);
System.out.println("\nChanges DO NOT reflect in other map \n");
clonedMap.get(1).setName("Charles");
System.out.println(employeeMap);
System.out.println(clonedMap);
结果:
{1=Employee [id=1, name=Alex, dob=1990-01-01], 2=Employee [id=2, name=Bob, dob=1990-02-01]}
Changes DO NOT reflect in other map
{1=Employee [id=1, name=Alex, dob=1990-01-01], 2=Employee [id=2, name=Bob, dob=1990-02-01]}
{1=Employee [id=1, name=Charles, dob=1990-01-01], 2=Employee [id=2, name=Bob, dob=1990-02-01]}
为什么要用 Gson
为什么不使用 ObjectMapper 或者其他常用的序列化工具,而要额外引入 Gson包呢?在官方库看到这样一段描述:
There are a few open-source projects that can convert Java objects to JSON.
However, most of them require that you place Java annotations in your classes;
something that you can not do if you do not have access to the source-code. Most also
do not fully support the use of Java Generics. Gson considers both of these as very
important design goals.
大意是说:(1)为了序列化,其他的库需要在预先在类上加注解,有时用户拿不到类的源代码,就无法做到加注解。(2)打多数的序列化库不支持泛型。Gson 在设计的时候就着重考虑到了这两点。
|