如何在Java中复制HashMap(不是浅拷贝)
我需要复制HashMap<Integer, List >
但是当我在副本中更改某些内容时,我希望原始内容保持不变。 即,当我从副本中删除List
中的某些内容时,它将保留在原始List
中的List
中。
如果我理解正确,这两个方法只会创建浅层副本,这不是我想要的:
mapCopy = new HashMap(originalMap); mapCopy = (HashMap) originalMap.clone();
我对吗?
有没有比这更好的方法来迭代所有键和所有列表项并手动复制它?
你是对的,浅版不符合你的要求。 它将从原始映射中获得List
的副本,但这些List
将引用相同的List
对象,因此从一个HashMap
对List
的修改将出现在来自其他HashMap
的相应List
。
在Java中没有为HashMap
提供深度复制,因此您仍然需要遍历所有条目put
它们放入新的HashMap
。 但是你也应该每次都复制一份List
。 像这样的东西:
public static HashMap> copy( HashMap> original) { HashMap> copy = new HashMap>(); for (Map.Entry> entry : original.entrySet()) { copy.put(entry.getKey(), // Or whatever List implementation you'd like here. new ArrayList (entry.getValue())); } return copy; }
如果要修改单个MySpecialClass
对象,并且更改未反映在复制的HashMap
的List
中,则还需要制作它们的新副本。
遗憾的是,这确实需要迭代。 但是Java 8流非常简单:
mapCopy = map.entrySet().stream() .collect(Collectors.toMap(e -> e.getKey(), e -> new ArrayList(e.getValue()));
编辑:在Java的更高版本中, e -> List.copyOf(e.getValue())
将是首选。
你可以尝试深度克隆。 请访问https://code.google.com/p/cloning/查看示例
您正在制作HashMap本身的副本,因此更改HashMap副本不会更改原始HashMap(即添加或删除条目),但由于您存储的对象不是基本类型,因此使用给定键检索的List无论是从第一个地图还是第二个地图中检索,都是相同的。
因此,该列表仍然只有一个副本,由两个映射引用:无论您使用哪个引用来访问它,更改List都会更改它。
如果您希望实际的List是一个单独的副本,您将必须按照您的说法执行操作:迭代HashMap的条目集并手动创建每个List的副本,然后将其添加到新映射中。
如果有更好的方法,我不知道它是什么。
然后序列化为json并反序列化:
Map originalMap = new HashMap<>(); String json = new Gson().toJson(originalMap); Map mapCopy = new Gson().fromJson( json, new TypeToken
对于特殊类,您可能需要编写自定义反序列化程序 。