Note: this is not a duplicate of the many questions asking how to remove an item from a map during iteration.
I encountered some surprising edge cases when using a hash map iterator to remove an item from a map.
The following code crashes with with the a ConcurrentModificationException
.
Map<Integer, Integer> m = new HashMap<>();
m.put(1, 1);
m.put(2, 2);
m.put(3, 3);
for (Iterator<Map.Entry<Integer, Integer>> iterator = m.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<Integer, Integer> e = iterator.next();
if (e.getKey() == 2) {
iterator.remove();
}
m.remove(2); // This causes the crash
}
Unsurprisingly, the following code does not:
Map<Integer, Integer> m = new HashMap<>();
m.put(1, 1);
m.put(2, 2);
m.put(3, 3);
for (Iterator<Map.Entry<Integer, Integer>> iterator = m.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<Integer, Integer> e = iterator.next();
if (e.getKey() == 2) {
iterator.remove();
}
m.remove(4); // No crash here
}
However, the following code also does not crash:
Map<Integer, Integer> m = new HashMap<>();
m.put(2, 2);
m.put(3, 3);
for (Iterator<Map.Entry<Integer, Integer>> iterator = m.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<Integer, Integer> e = iterator.next();
if (e.getKey() == 2) {
iterator.remove();
}
m.remove(2); // Also no crash?
}
The only difference between the first and third examples are the removal of the <1, 1> entry. Why does calling Map.remove only crash sometimes? Is this specified in the standard anywhere?