如何在Java中复制HashMap(不是浅拷贝)

时间:2015-02-02 23:07:47

标签: java hashmap copy

我需要制作HashMap<Integer, List<MySpecialClass> >的副本,但是当我在副本中更改某些内容时,我希望原始内容保持不变。即当我从副本List<MySpecialClass>中删除某些内容时,它会保留在原始版本的List<MySpecialClass>中。

如果我理解正确的话,这两种方法只能创建浅层副本,这不是我想要的:

mapCopy = new HashMap<>(originalMap);
mapCopy = (HashMap) originalMap.clone();

我是对的吗?

有没有更好的方法来迭代所有键和所有列表项并手动复制?

6 个答案:

答案 0 :(得分:25)

遗憾的是,这确实需要迭代。但是Java 8流程非常简单:

mapCopy = map.entrySet().stream()
    .collect(Collectors.toMap(e -> e.getKey(), e -> new ArrayList(e.getValue()));

编辑:在Java的更高版本中,首选e -> List.copyOf(e.getValue())

答案 1 :(得分:19)

你是对的,浅色副本不符合你的要求。它将包含原始地图中List的副本,但这些List将引用相同的List个对象,以便从一个List修改HashMap List将显示在其他HashMap的相应HashMap中。

在Java中没有为put提供深度复制,因此您仍然需要遍历所有条目,并在新HashMapList。但是你也应该每次复制public static HashMap<Integer, List<MySpecialClass>> copy( HashMap<Integer, List<MySpecialClass>> original) { HashMap<Integer, List<MySpecialClass>> copy = new HashMap<Integer, List<MySpecialClass>>(); for (Map.Entry<Integer, List<MySpecialClass>> entry : original.entrySet()) { copy.put(entry.getKey(), // Or whatever List implementation you'd like here. new ArrayList<MySpecialClass>(entry.getValue())); } return copy; } 。像这样:

MySpecialClass

如果您要修改单个List个对象,并且更改未反映在复制的HashMap的{​​{1}}中,则您需要制作新的副本他们也是。

答案 2 :(得分:6)

然后序列化为json并反序列化:

Map<String, Object> originalMap = new HashMap<>();
String json = new Gson().toJson(originalMap);
Map<String, Object> mapCopy = new Gson().fromJson(
    json, new TypeToken<Map<String, Object>>() {}.getType());

对于特殊课程,您可能需要write a custom deserializer

答案 3 :(得分:2)

您可以尝试深度克隆。请查看https://code.google.com/p/cloning/

上的示例

答案 4 :(得分:1)

您正在制作HashMap本身的副本,因此更改HashMap副本不会更改原始HashMap(即添加或删除条目),但由于您存储的对象不是基本类型,因此您检索的List无论是从第一个地图还是第二个地图检索,给定的密钥都是相同的。

因此,该列表仍然只有一个副本,由两个映射引用:无论您使用哪个引用来访问它,更改List都会更改它。

如果你想让实际的List成为一个单独的副本,你必须按照你的说法去做:迭代HashMap的入口集并手动创建每个List的副本,然后将它添加到新地图中

如果有更好的方法,我不知道它是什么。

答案 5 :(得分:0)

只需使用 Apache Commons Lang - SerializationUtils.clone();

类似这些:

    Map<String, List<MySpecialClass>> originalMap = new HashMap();
    HashMap<String, List<MySpecialClass>> deepCopy = SerializationUtils.clone(new HashMap<>(originalMap));

还要确保 MySpecialClass 实现了 Serializable 接口。

public class MySpecialClass implements Serializable{}