TonyW
TonyW

Reputation: 18875

Update HashMap values of type HashSet<Integer>

I have trouble updating the HashMap values of Set type. After initializing the HashMap with key-values pair, I want to insert a new value to the the existing value Set, and the new value is to be incremented for each insert. My code is following:

    public static void main(String[] args)
    {
        String[] mapKeys = new String[]{"hello", "world", "america"};
        Map<String, Set<Integer>> hashMap1 = new HashMap<String, Set<Integer>>();
        Set<Integer> values = new HashSet<Integer>();

        for (int i = 0; i < 10; i++)  // initialize the values to a set of integers[1 through 9]
        {
            values.add(i);
        }

        for (String key : mapKeys)
        {
            hashMap1.put(key, values);
        }

        StdOut.println("hashMap1 is: " + hashMap1.toString());

        int newValues = 100; // insert this newValues (incremented at each insert) to each value
        Set<Integer> valuesCopy;

        for (String key : mapKeys)
        {
            if (hashMap1.containsKey(key))
            {
                valuesCopy = hashMap1.get(key); // first, copy out the existing values

                valuesCopy.add(newValues++); // insert the newValues to the value Set
                hashMap1.remove(key);// remove the existing entries
                hashMap1.put(key, valuesCopy); // insert the key-value pairs

            }
        }

        StdOut.println("the updated hashMap1 is: " + hashMap1.toString());


    }

When executing the code, each HashMap key is associated with the same set of Integers: [102, 0, 1, 2, 100, 3, 101, 4, 5, 6, 7, 8, 9], however, what I really want is insert only one number to each set, this is what I want: [0, 1, 2, 100, 3, 4, 5, 6, 7, 8, 9]

I need help understanding this: why all the new inserted values are the same? how to make it work as I wish? thanks for help

Upvotes: 0

Views: 10453

Answers (2)

Siyuan Ren
Siyuan Ren

Reputation: 7844

The reason is that the every object symbol in Java is a reference to the actual object. In this part

for (String key : mapKeys)
{
    hashMap1.put(key, values);
}

you associate each key with the reference to the same Set<Integer>, so when you change one of them, all of them are changed.

The correct way to do this is

for (String key : mapKeys)
{
    hashMap1.put(key, new HashSet<Integer>(values));
}

This way every key will have its own copy of Set initialized with the content of values.

With this fact, you can also see that the code here

            valuesCopy = hashMap1.get(key); // first, copy out the existing values

            valuesCopy.add(newValues++); // insert the newValues to the value Set
            hashMap1.remove(key);// remove the existing entries
            hashMap1.put(key, valuesCopy); // insert the key-value pairs

is verbose and introduces unnecessary overhead. Simply use

hashMap1.get(key).add(newValues++);

Upvotes: 3

Engine Bai
Engine Bai

Reputation: 626

First of all, when you execute if (hashMap1.containsKey(key)), the java loops to check each key to check existence of key automatically, so that you don't need to write the for loop code by yourself.

Then, you don't need to write hashMap1.remove(key) because that when insert a exist key to java map, the map will find the existed (key, value) pair and overwrite the new (key, value) pair.

Here is the modified code after Set<Integer> valuesCopy;:

if (hashMap1.containsKey(key))
{
    valuesCopy = hashMap1.get(key); // first, copy out the existing values
    valuesCopy.add(newValues++); // insert the newValues to the value Set
    hashMap1.put(key, valuesCopy); // insert the key-value pairs
}

Just remove for (String key : mapKeys) and hashMap1.remove(key) code segment, and then you may get the result that you want.

Upvotes: 1

Related Questions