How to copy HashMap (not shallow copy) in Java

JavaHashmapCopy

Java Problem Overview


I need to make a copy of HashMap<Integer, List<MySpecialClass> > but when I change something in the copy I want the original to stay the same. i.e when I remove something from the List<MySpecialClass> from the copy it stays in the List<MySpecialClass> in the original.

If I understand it correctly, these two methods create just shallow copy which is not what I want:

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

Am I right?

Is there a better way to do it than just iterate through all the keys and all the list items and copy it manually?

Java Solutions


Solution 1 - Java

This does need iteration unfortunately. But it's pretty trivial with Java 8 streams:

mapCopy = map.entrySet().stream()
    .collect(Collectors.toMap(e -> e.getKey(), e -> List.copyOf(e.getValue())))

Solution 2 - Java

You're right that a shallow copy won't meet your requirements. It will have copies of the Lists from your original map, but those Lists will refer to the same List objects, so that a modification to a List from one HashMap will appear in the corresponding List from the other HashMap.

There is no deep copying supplied for a HashMap in Java, so you will still have to loop through all of the entries and put them in the new HashMap. But you should also make a copy of the List each time also. Something like this:

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;
}

If you want to modify your individual MySpecialClass objects, and have the changes not be reflected in the Lists of your copied HashMap, then you will need to make new copies of them too.

Solution 3 - Java

Serialize to json and deserialize afterwards:

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());

For special classes you might need to write a custom deserializer.

Solution 4 - Java

Just use Apache Commons Lang - SerializationUtils.clone();

Something like these:

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

Also make sure MySpecialClass implements Serializable interface.

public class MySpecialClass implements Serializable{}

Solution 5 - Java

You are making a copy of the HashMap itself, so changing the HashMap copy will not change the original HashMap (i.e. adding or removing entries), but because the objects you have stored are not primitive types, the List that you retrieve with a given key will be the same whether retrieved from the first or the second Map.

Thus, there is still only ONE copy of that list, referenced by both maps: changing the List changes it no matter which reference you use to access it.

If you want the actual List to be a separate copy, you will have to do as you said: iterate over the entry set of the HashMap and create a copy of each List manually, adding it to the new map as you go.

If there is a better way than that, I don't know what it is.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMathisView Question on Stackoverflow
Solution 1 - JavasprinterView Answer on Stackoverflow
Solution 2 - JavargettmanView Answer on Stackoverflow
Solution 3 - Javaneu242View Answer on Stackoverflow
Solution 4 - JavaІгор КолобовView Answer on Stackoverflow
Solution 5 - JavaBrianView Answer on Stackoverflow