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

Mat*_*his 36 java copy hashmap

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

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

mapCopy = new HashMap<>(originalMap);
mapCopy = (HashMap) originalMap.clone();
Run Code Online (Sandbox Code Playgroud)

我对吗?

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

spr*_*ter 28

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

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

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

  • 我对流不太熟悉。当我尝试您的解决方案时,它给出了一个错误:无法从静态上下文中引用非静态方法 getKey(),与 getValue() 相同,如何对其进行编辑以使其正常工作?谢谢 (2认同)
  • getValue()不会只是传递引用吗? (2认同)

rge*_*man 20

你是对的,浅拷贝不符合你的要求.这将有副本List期从原来的地图,但这些List旨意指的是同一个List对象,以便于修改List从一个HashMap将出现在相应的List从另一个HashMap.

HashMap在Java中没有为Java 提供深度复制,因此您仍然需要遍历所有条目以及put新的条目HashMap.但是你也应该List每次复制一份.像这样的东西:

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;
}
Run Code Online (Sandbox Code Playgroud)

如果要修改单个MySpecialClass对象,并且更改未反映在List复制的s中HashMap,则还需要制作它们的新副本.


neu*_*242 13

序列化为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());
Run Code Online (Sandbox Code Playgroud)

对于特殊的类,您可能需要编写一个自定义反序列化器

  • 我猜这是关于这项技术的性能损失的投票,但是IMO尽管有性能损失,但这是一个合法的答案。 (3认同)

Іго*_*бов 10

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

像这样的东西:

    Map<String, List<MySpecialClass>> originalMap = new HashMap();
    HashMap<String, List<MySpecialClass>> deepCopy = SerializationUtils.clone(new HashMap<>(originalMap));
Run Code Online (Sandbox Code Playgroud)

还要确保 MySpecialClass 实现 Serialized 接口。

public class MySpecialClass implements Serializable{}
Run Code Online (Sandbox Code Playgroud)