Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to copy HashMap (not shallow copy) in Java

Tags:

java

hashmap

copy

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?

like image 475
Mathis Avatar asked Feb 02 '15 23:02

Mathis


People also ask

How do I deep clone a HashMap?

The most effective way to deep clone a Java object is serialization. The same applies to deep clone a HashMap as well. Here, we are using Google Gson library to serialize the HashMap and deserialize to create HashMap deep copy.

How do I copy a HashMap?

Instead of iterating through all of the entries, we can use the putAll() method, which shallow-copies all of the mappings in one step: HashMap<String, Employee> shallowCopy = new HashMap<>(); shallowCopy. putAll(originalMap); We should note that put() and putAll() replace the values if there is a matching key.

Can we clone HashMap in Java?

The Java HashMap clone() method makes the shallow copy of the hashmap and returns it. Here, the shallow copy means the keys and values are not copied. Instead, references to keys/values are copied. To learn more about the shallow copy, visit Java Shallow Copy.


2 Answers

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()))) 
like image 133
sprinter Avatar answered Sep 21 '22 01:09

sprinter


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.

like image 38
rgettman Avatar answered Sep 17 '22 01:09

rgettman