Search code examples
javacopyhashmapclone

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

Solution

  • 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