Reputation: 18875
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
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
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