6

I have a map (Map<String, Set<String>>), and want to copy the map to a new map object. However, if I just feed the map to the say HashMap constructor (new HashMap<String, Set<String>>(oldMap)) it won't do a full copy, and only copies the reference to the set, which can be modified and those changes will be reflected in the new map.

Is there a more simply way of doing a full copy other than iterating over each key/value pair and creating a new HashSet for each set then adding that to the map?

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
cole
  • 63
  • 1
  • 1
  • 5
  • I think this is basically a duplicate of [this question](http://stackoverflow.com/questions/13049222/java-hashmap-deep-copy) of deep copying a map. There are several resources listed on that question.. – hineroptera Dec 20 '13 at 16:37
  • Iterating is the only clean and fast way. Shouldn't take more than 3 lines of code. – JB Nizet Dec 20 '13 at 16:40

3 Answers3

1

There was some discussion on this here for deep cloning:

Java HashMap - deep copy

It's hard in this situation though as the new map and set need to rebuild themselves. Do you also need to clone the contents of the Set? If so then you could just serialize then de-serialize the whole collection.

Iterating yourself will almost certainly be faster and will let you control how deep the cloning goes. Serializing will be slower but so long as everything in the object tree is serializable it will copy everything in the object tree and maintain things like circular references etc. (For example if you had 2 keys in the map pointing to the same Set object then iterating will split that into 2 sets, serializing will maintain the link).

Community
  • 1
  • 1
Tim B
  • 40,716
  • 16
  • 83
  • 128
  • True, but at some point in the future there may be something other than Strings in the Set. – Tim B Dec 20 '13 at 16:43
  • Yes, I need to clone the contents of the set. The google library seems like it could be effective but I'm trying to keep the project as lightweight as possible. Is there any reason that serialization/deserialization would be a better approach then just iterating over the map and creating a new set for each key/value pair? – cole Dec 20 '13 at 16:43
  • The set is actually not implementing strings in my particular scenario, just didn't feel like complicating the question with my custom object. – cole Dec 20 '13 at 16:44
  • Sometimes simplifying too much obscures the answer, if I had made the "String immutable" assumption it might change things in my answer. See edit for more details on the two approaches. – Tim B Dec 20 '13 at 16:46
  • Thanks for the answer, I have all the information I need to make the best decision here. – cole Dec 20 '13 at 16:51
  • No worries. For what it's worth I would probably go down the iteration approach unless I needed to worry about objects being referenced from multiple places. – Tim B Dec 20 '13 at 16:52
1

If you don't want to use external library and just want to copy this specific map you can do:

HashMap<String, HashSet<String>> copy = new HashMap<>();
for(String newKey : oldMap.keySet()){
    copy.put(newKey, new HashSet<String>(oldMap.get(newKey)));
}

Where oldMap is the map you are trying to copy. This worked for me.

Moe
  • 91
  • 2
  • 10
0

You need deep cloning. Have a look for example at https://code.google.com/p/cloning/

Jakub Kotowski
  • 7,411
  • 29
  • 38