How to avoid ConcurrentModificationException for map or List

The ConcurrentModificationException exception is thrown due to one thread trying to read the object and the other thread trying to modify the object.

This happens to all java collection API classes - List, HashMap, HashTable, LinkedHashMap

In the below example

  • Create an ArrayList of Strings.
  • Create an Iterator using Iterate using the iterator() method
  • Check for the next element exists or not using the hasNext() method
  • if the next element exists, Print the element
  • During iteration, Trying to remove an element based on a Conditional check
  • This will throw an error Exception in thread "main" java.util.ConcurrentModificationException

ArrayList throws java.util.ConcurrentModificationException while removing an item during iteration

Here are the examples

  • Single thread is reading list using iterator and
  • Removing an element during iteration causes this exception

java.util.Iterator are fail-fast iteration that throws an error during iteration and modifies a collection.

import java.util.ArrayList;
import java.util.Iterator;

public class App {
    public static void main( String[] args ){
        ArrayList<String> list = new ArrayList<>();
        list.add("one");
        list.add("two");
        list.add("four");
        list.add("five");

        Iterator<String> strIterator = list.iterator();
        while (strIterator.hasNext()) {
            String nextString = strIterator.next();
            System.out.println("Current Object: " + nextString);
            if (nextString.equals("five"))
                list.remove(nextString);
        }
    }
}

Output

Current Object: one
Current Object: two
Current Object: three
Current Object: four
Current Object: five
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
    at java.util.ArrayList$Itr.next(ArrayList.java:851)
    at App.main(App.java:15)

Process finished with exit code 1

This is not possible to remove an element from the array list with the list.remove() method during iteration. list.remove() method is not safe to remove an element during iteration.

How to iterate list avoiding ConcurrentModificationException while removing objects

It is a solution or fix for ConcurrentModificationException for the java list.

You can use the remove() method from java.util.Iterator instead of list.remove()

Iterator.remove is a safe method to change collection during iteration.

import java.util.ArrayList;
import java.util.Iterator;

public class App {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
        list.add("five");

        Iterator<String> strIterator = list.iterator();
        while (strIterator.hasNext()) {
            String nextString = strIterator.next();
            System.out.println("Current Object: " + nextString);
            if (nextString.equals("five"))
                strIterator.remove();
        }
        System.out.println(list);
    }
}

HashMap concurrently modified exception

This happens for the below map and list of collections.

  1. Modifying the state of any key or value in map implementations(example,) during an iteration of Map objects
  2. Adding/removing (Iterator.remove) the object is a collections class while iteration of collection of objects at the same time.
  3. Below example does not throw this exception as changing the key and value and hashmap size is not changing, This is an example of modifying the collection while iteration of hashmap.

Iteration is done in three ways - iterator, map.entrySet with loop.

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class App {
    public static void main(String[] args) {

        HashMap<String, String> mapDemo = new HashMap<>();

        mapDemo.put("key-1", "value-1");
        mapDemo.put("key-2", "value-2");
        mapDemo.put("key-3", "value-3");

        Iterator<String> iterator = mapDemo.keySet().iterator();
        while(iterator.hasNext()) {
            String key = iterator.next();
            System.out.println("Map Value:" + mapDemo.get(key));
            if (key.equals("key-2")) {
                mapDemo.put("key-2", "newvalue");
            }
        }

        for (Map.Entry<String, String> entry : mapDemo.entrySet()) {
            if (entry.getKey().contains("key-2")) {
                entry.setValue("new Value-2");
            }
        }
        for (Map.Entry entry : mapDemo.entrySet()) {
            System.out.println(entry.getKey() + "===" + entry.getValue());
        }
    }


}

Output

Map Value:value-1
Map Value:value-3
Map Value:value-2
key-1===value-1
key-3===value-3

java8 to fix ConcurrentModificationException with removeIf method

java8 introduced the removeIf method in collections classes.

import java.util.ArrayList;

public class App {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
        list.add("five");
        System.out.println(list);
        list.removeIf(item -> item == "five");
        System.out.println(list);

    }
    }
[one, two, three, four, five]
[one, two, three, four]

How to avoid ConcurrentModificationException in java?

ConcurrentModificationException thrown in single threaded and multi threaded applications.

  • You can use ConcurrentHashMap, ConcurrentSkipListMap,ConcurrentLinkedQueue, CopyOnWriteArrayList ,CopyOnWriteArrayList classes from java.util.concurrent modules in java7 version onwards.
  • You can use Iterator. remove removing an object from the collection during iteration
  • You can also use synchronized block by having a lock on collections, thus decreasing performance, but not safe to use it
  • You can also use the removeIf method from java8

Conclusion

To Sump up, We have seen ConcurrentModifiedException for collections during modifying an object while doing iteration, and solutions are specified for List and Map, with java8.