Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HashMap Copy behavior I can't figure out

I am having trouble getting a separate copy of my HashMaps. By that I mean, once I have made a copy of the original, making a change to one does not change the other.

I have two HashMaps in this format:

HashMap<String, List<String> one = new HashMap<String, List<String>();
HashMap<String, List<String> two = new HashMap<String, List<String>();

I call the following function below (getTabSetDifferences) passing in one and two, as expected if there are some differences, those values will be removed from the HashMap and it'll be different than before it was passed in for the test.

I want them to remain unchanged, so tried passsing in:

getTabSetDifferences((HashMap)one.clone(), (HashMap)two.clone())

This still changed the originals, so i created two more hashmaps in the same format, and cloned one and two to them, I used the new hashmaps to pass in, and the original was still changed.

I then tried:

HashMap<String, List<String>> holdOne = new HashMap<String, List<String>>();
holdOne.putAll(one);

HashMap<String, List<String>> Holdtwo = new HashMap<String, List<String>>();
holdTwo.putAll(two);

Now I can do something like:

holdTwo.remove(key);

and the original is not changed, but if i call the method with holdOne and holdTwo it still changes the original one and two hashmaps, shouldn't they remain? The method is working, and finding the differences i want, and is returned. But I still need the original two hashmaps to be as they were, but no matter which way I call, what ever changes are made to holdOne and holdTwo changes the originals. Is that the expected behavior? If so, what is the proper way to get a copy of a hashmap that is not tied to it.

getTabSetDifferences(holdOne, holdTwo);

public HashMap<String, List<String>> getTabSetDifferences(HashMap<String, List<String>> hmMain, HashMap<String, List<String>> hmSecond)   {
    HashMap<String, List<String>> hmDifferences = new HashMap<String, List<String>>();
    for (Map.Entry<String, List<String>> entry : hmMain.entrySet()) {
        if(hmSecond.containsKey(entry.getKey())) {
            entry.getValue().removeAll(hmSecond.get(entry.getKey()));
            if (entry.getValue().size() > 0)
                hmDifferences.put(entry.getKey(), entry.getValue());
        }
        else {
            hmDifferences.put(entry.getKey(), entry.getValue());
        }
    }
    return hmDifferences;
}
like image 951
Green Avatar asked Oct 20 '11 16:10

Green


2 Answers

The clone method doesn't do a deep copy.

You have 2 options.

  1. create a deep copy method.
  2. Use one of the Map implementations from the java.util.concurrent package like copyOnWrite
like image 77
Basanth Roy Avatar answered Sep 18 '22 05:09

Basanth Roy


I suspect you are only copying the keys/values. This will not create copies of the lists.

Perhaps Guava's MultiMap is what you want?

like image 34
Peter Lawrey Avatar answered Sep 18 '22 05:09

Peter Lawrey