java.util.ConcurrentModificationException | Code Factory

Code Factory
3 min readApr 22, 2020

--

Reference Link : Link

Donate : Link

java.util.ConcurrentModificationException is a very common exception when working with Java collection classes. Java Collection classes are fail-fast, which means if the Collection will be changed while some thread is traversing over it using iterator, the iterator.next() will throw ConcurrentModificationException. Concurrent modification exception can come in case of multithreaded as well as a single threaded java programming environment.

Let’s see the concurrent modification exception scenario with an example.

ConcurrentModificationExceptionExample.java

package com.codeFactory;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class ConcurrentModificationExceptionExample {public static void main(String args[]) {
List<String> myList = new ArrayList<String>();
myList.add("1");
myList.add("2");
myList.add("3");
myList.add("4");
myList.add("5");
Iterator<String> it = myList.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println("List Value : " + value);
if (value.equals("3"))
myList.remove(value);
}
Map<String, String> myMap = new HashMap<String, String>();
myMap.put("1", "1");
myMap.put("2", "2");
myMap.put("3", "3");
Iterator<String> it1 = myMap.keySet().iterator();
while (it1.hasNext()) {
String key = it1.next();
System.out.println("Map Value : " + myMap.get(key));
if (key.equals("2")) {
myMap.put("1", "4");
// myMap.put("4", "4");
}
}
}
}

Above program will throw java.util.ConcurrentModificationException when executed, as shown in below console logs.

Output :

List Value : 1
List Value : 2
List Value : 3
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at com.codeFactory.ConcurrentModificationExceptionExample.main(ConcurrentModificationExceptionExample.java:21)

From the output stack trace, its clear that the concurrent modification 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. modCount provides the number of times list size has been changed. modCount value is used in every next() call to check for any modifications in a function checkForComodification().

Now comment out the list part and run the program again. You will see that there is no ConcurrentModificationException being thrown now.

Output will be :

Map Value : 1
Map Value : 2
Map Value : 3

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 a 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

  • 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.
  • 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.
  • If you are using JDK 1.5 or higher then you can use ConcurrentHashMap and CopyOnWriteArrayList classes. This is the recommended approach to avoid concurrent modification exception.

Let us run an example using Concurrent Collection classes :

ConcurrentModificationExceptionExample.java

package com.codeFactory;import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConcurrentModificationExceptionExample {public static void main(String args[]) {
List<String> myList = new CopyOnWriteArrayList<String>();
myList.add("1");
myList.add("2");
myList.add("3");
myList.add("4");
myList.add("5");
Iterator<String> it = myList.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println("List Value : " + value);
if (value.equals("2")) {
myList.remove("4");
myList.add("6");
myList.add("7");
}
}
System.out.println("List Size : " + myList.size());
Map<String, String> myMap = new ConcurrentHashMap<String, String>();
myMap.put("1", "1");
myMap.put("2", "2");
myMap.put("3", "3");
Iterator<String> it1 = myMap.keySet().iterator();
while (it1.hasNext()) {
String key = it1.next();
System.out.println("Map Value : " + myMap.get(key));
if (key.equals("2")) {
myMap.remove("3");
myMap.put("4", "4");
myMap.put("5", "5");
}
}
System.out.println("Map Size : " + myMap.size());
}
}

The output of the above program is shown below. You can see that there is no ConcurrentModificationException being thrown by the program.

Output :

List Value : 1
List Value : 2
List Value : 3
List Value : 4
List Value : 5
List Size : 6
Map Value : 1
Map Value : 2
Map Value : null
Map Value : 4
Map Value : 5
Map Size : 4

--

--