to understand this lets look at source of HashMap implementation:
public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable{
which contains HashIterator as below:
private abstract class HashIterator {
...
int expectedModCount = modCount;
...
HashMapEntry<K, V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
....
}
every time you create a iterator:
- a counter expectedModCount is created and is set to value of modCount as entry checkpoint
- modCount is incremented in cases of use put/get (add/remove)
- nextEntry method of iterator is checking this value with current modCount if they are different concurrent modification exception is throw
to avoid this u can:
- convert map to an array (not recommended for large maps)
- use concurrency map or list classes (CopyOnWriteArrayList / ConcurrentMap)
- lock map (this approach removes benefits of multithreading)
this will allow you to iterate and add or remove elements at the same time without rising an exception
Concurrency map/list iterator is a "weakly consistent" iterator that will
never throw ConcurrentModificationException, and guarantees to
traverse elements as they existed upon construction of the iterator,
and may (but is not guaranteed to) reflect any modifications
subsequent to construction.
More info on CopyOnWriteArrayList