0

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

2 Answers 2

3

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++);
Sign up to request clarification or add additional context in comments.

5 Comments

but when I do hashMap1.put(key, hashMap1.get(key).add(newValues++)); it gives me data-type incompatible error.
@TonyGW: You don't use put again. The get returns a reference to the underlying HashSet. So when you calls the add function on it, the original one associated with your key changes too.
@TonyGW: You still don't understand the idea of reference, do you?
this: hashMap1.get(key).add(newValues++); does not work for me. It gives this wrong result: [102, 0, 1, 2, 100, 3, 101, 4, 5, 6, 7, 8, 9] in the HashMap values, which should be [0, 1, 2, 100, 3, 4, 5, 6, 7, 8, 9]
@TonyGW: Because you didn't adopt this change: hashMap1.put(key, new HashSet<Integer>(values));.
1

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.

2 Comments

thanks, but I need to insert the new value to the existing values in the map. So I guess I need to get the existing values based on the key. right?
Correct! You have to get the exist (key,value) pair, modify the value and just put (key, new_value) back the map. (no need to remove the existed (key, value) pair)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.