Learnitweb

How to avoid ConcurrentModificationException while iterating a collection?

ConcurrentModificationException is thrown if the collection is changed while a thread is traversing over it using iterator. ConcurrentModificationException can occur both in single threaded as well as multi-threaded programs. For example, following program will throw ConcurrentModificationException because we are trying to remove element from the list while iterating:

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

public class ConcurrentModificationExceptionExample {

	public static void main(String args[]) {
		List<String> list = new ArrayList<String>();

		list.add("one");
		list.add("two");
		list.add("three");
		list.add("four");
		list.add("five");
		
		Iterator<String> it = list.iterator();
		while (it.hasNext()) {
			String element = it.next();
			System.out.println("List Value:" + element);
			if ("three".equals(element))
				list.remove(element);
		}
	}
}

Output

List Value:one
List Value:two
List Value:three
Exception in thread "main" java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
  at java.util.ArrayList$Itr.next(ArrayList.java:859)
  at ConcurrentModificationExceptionExample.main(ConcurrentModificationExceptionExample.java:18)

To avoid ConcurrentModificationException

  • Convert the list in to an array and then iterate array. This approach is not good in case of large size list.
  • Use CopyOnWriteArrayList and ConcurrentHashMap if you are using JDK1.5 or higher.
  • Use synchronized block while iterating over list. This approach is not recommended due to performance issues.
  • Use remove() function of iterator to remove element from the collection. But is the case you can remove the current element but not any other element.

Following example shows ConcurrentModificationException will not be thrown when CopyOnWriteArrayList is used.

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListExample {

	public static void main(String[] args) {
		List<String> list = new CopyOnWriteArrayList<String>();

		list.add("one");
		list.add("two");
		list.add("three");
		list.add("four");
		list.add("five");
		
		Iterator<String> it = list.iterator();
		while (it.hasNext()) {
			String element = it.next();
			System.out.println("List Value:" + element);
			if ("three".equals(element))
				list.remove(element);
		}

	}
}

Output

List Value:one
List Value:two
List Value:three
List Value:four
List Value:five

Following example will demonstrate that ConcurrentModificationException is not thrown when we use remove() function of iterator.

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

public class IteratorRemoveExample {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();

		list.add("one");
		list.add("two");
		list.add("three");
		list.add("four");
		list.add("five");
		
		Iterator<String> itr = list.iterator();
		while (itr.hasNext()) {
			String element = itr.next();
			System.out.println("List Value:" + element);
			if ("three".equals(element))
				itr.remove();
		}
		System.out.println("final list: " + list);

	}
}

Output

List Value:one
List Value:two
List Value:three
List Value:four
List Value:five
final list: [one, two, four, five]