Java Collection classes are fail-fast which means that if the Collection
will be changed while some thread is traversing over it using iterator,
the iterator.next() will throw a
ConcurrentModificationException.
This situation can come in case of multithreaded as well as single threaded environment.
Lets explore this scenario with the following example :
From the output stack trace, its clear that the exception is coming
when we call iterator next() function. If you are wondering how Iterator
checks for the modification, its implementation is present in
AbstractList class where an int variable modCount is defined that
provides the number of times list size has been changed. This value is
used in every next() call to check for any modifications in a function
checkForComodification().
Now comment the list part and run the program again.
Output will be:
Map Value:3
Map Value:2
Map Value:4
Since we are updating the existing key value in the myMap, its size
has not been changed and we are not getting
ConcurrentModificationException. Note that the output may differ in your
system because HashMap keyset is not ordered like list. If you will
uncomment the statement where I am adding a new key-value in the
HashMap, it will cause ConcurrentModificationException.
To Avoid ConcurrentModificationException in multi-threaded environment:
1.
You can convert the list to an array and then iterate on the array.
This approach works well for small or medium size list but if the list
is large then it will affect the performance a lot.
2. You can
lock the list while iterating by putting it in a synchronized block.
This approach is not recommended because it will cease the benefits of
multithreading.
3. If you are using JDK1.5 or higher then you can
use ConcurrentHashMap and CopyOnWriteArrayList classes. It is the
recommended approach.
To Avoid ConcurrentModificationException in single-threaded environment:
You
can use the iterator remove() function to remove the object from
underlying collection object. But in this case you can remove the same
object and not any other object from the list.
Let us run an example using Concurrent Collection classes: