If I iterate over a standard HashMap
and attempt to add elements to it while iterating I get ConcurrentModificationException
.
So I try an HashMap allowing concurrent adds:
ConcurrentHashMap<String, Integer> cMap = new ConcurrentHashMap<>();
cMap.put("one", 1);
cMap.forEach((key, value) -> cMap.put(key + key, value + value));
System.out.println(cMap);
However, the resulting map is a bit weird:
{oneoneoneoneoneoneoneone=8, one=1, oneone=2, oneoneoneone=4}
and if changing the key to zx (cMap.put("zx", 1)
), the result is now:
{zxzx=2, zx=1}
Questions:
1) Why this happens? The two concurrent operations (iterating and adding) should not conflict.
2) How to fix the inconsistency?
As opposite to Collections, when changing a String while iterating over the chars of that String, this issue is not being met:
String str = scanner.next();
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i) == str.charAt(i-1)) {
str = str.substring(0, i-1) + str.substring(i+1);
i = 0;
}
}
if (str.length() == 0) {
System.out.println("Empty String");
} else {
System.out.println (str);
}
}
note that in the above loop, the source String isn't actually changed but re-assigned because String is immutable and can not be modified.
The above code works fine and consistently. Is this an example of why Strings are thread safe?