How to copy HashMap (not shallow copy) in Java
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?
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())))
You're right that a shallow copy won't meet your requirements. It will have copies of the List
s from your original map, but those List
s 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 List
s of your copied HashMap
, then you will need to make new copies of them too.