why does this method not throw a concurrent modification? if if(next.equals("3") it does not. However, i change it to equals("1") it does. what is happening here?
private void checkConcurrentModification(){
Map<String, Integer> map = new HashMap<>();
map.put("1", 1);
map.put("2", 2);
map.put("3", 3);
Iterator<Entry<String, Integer>> iterator = map.entrySet().iterator();
while(iterator.hasNext()){
String next = iterator.next().getKey();
map.put(next, 1);
if(next.equals("3")){ //does not throw exception
//if(next.equals("1")){ //throws exception
map.put("4", 4);
}
}
for(Entry<String, Integer> entry : map.entrySet()){
System.out.println("entry key and value" +entry.getKey() + " : " +entry.getValue());
}
}
prints:
entry key and value1 : 1
entry key and value2 : 1
entry key and value3 : 1
entry key and value4 : 4
This depends on the the implementation of HashMap
.
If you run this under Java 7, then with the if (next.equals("3"))
it will throw a ConcurrentModificationException
, and with 1
, it won't.
If you run this under Java 8, then with 3
it will not throw the exception, and with 1
, it will.
The reason for this is that when you iterate the map under Java 7, the first key is going to be the 3
and the last is 1
. So you are modifying the value while you still have other values to iterate.
Under Java 8, the first key in the iteration is 1
and the last is 3
.
If you modify the map when you have encountered the last key, it will not check that modification, because it only checks it the next time you try to call next()
, but after the last value, hasNext()
returns false, so next()
is not called and the exception is avoided.