CopyOnWriteArrayList in Java is a thread safe implementation of List interface. CopyOnWriteArrayList was added in Java 1.5 and part of Collections framework.
Java ArrayList and ConcurrentModificationException
ArrayList is one of the basic implementations of List interface and it’s part of Java Collections Framework. We can use iterator to traverse through ArrayList elements.
Let’s check a sample program of ArrayList.
ConcurrentListExample.java
package com.journaldev.collections;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConcurrentListExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
// get the iterator
Iterator<String> it = list.iterator();
//manipulate list while iterating
while(it.hasNext()){
System.out.println("list is:"+list);
String str = it.next();
System.out.println(str);
if(str.equals("2"))list.remove("5");
if(str.equals("3"))list.add("3 found");
//below code don't throw ConcurrentModificationException
//because it doesn't change modCount variable of list
if(str.equals("4")) list.set(1, "4");
}
}
}
When we run above program, we get java.util.ConcurrentModificationException
as soon as the ArrayList is modified.
It happens because ArrayList iterator is fail-fast by design. What it means is that once the iterator is created, if the ArrayList is modified, it throws ConcurrentModificationException.
If you check the console log, you will notice that exception is thrown by Iterator next()
method. If you will look into the ArrayList source code, following method is called everytime we invoke next() on iterator that throws exception.
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
Here modCount
is the ArrayList variable that holds the modification count and every time we use add
, remove
or trimToSize
method, it increments. expectedModCount
is the iterator variable that is initialized when we create iterator with same value as modCount
. This explains why we don’t get exception if we use set
method to replace any existing element.
So basically iterator throws ConcurrentModificationException
if list size is changed.
CopyOnWriteArrayList in Java
Sometimes we want to add or remove elements from the list if we find some specific element, in that case we should use concurrent collection class – CopyOnWriteArrayList
. This is a thread-safe variant of java.util.ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.
CopyOnWriteArrayList introduces extra overload to the processing but it’s very effective when number of modifications are minimal compared to number of traversal operations.
If we change the implementation to CopyOnWriteArrayList
, then we don’t get any exception and below is the output produced.
list is:[1, 2, 3, 4, 5]
1
list is:[1, 2, 3, 4, 5]
2
list is:[1, 2, 3, 4]
3
list is:[1, 2, 3, 4, 3 found]
4
list is:[1, 4, 3, 4, 3 found]
5
Notice that it allows the modification of list, but it doesn’t change the iterator and we get same elements as it was on original list.
Hi Pankaj ,
As I checked the concept for concurrentmodification exception for ArrayList Object .
If we perform remove operation during Iteration ,It is working and throwing any exception .
And In case of add element in ArrayList during Iteration .It is throwing
Exception in thread “main” java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at com.collections.ArrayListExample.main(ArrayListExample.java:29)
Hi Vikas,
If we remove the element by using the list.remove() method then it will definitely throw ConcurrentModificationException
Reason -> In case of the list.remove() method the underlying iterator is not modified.
Where as in case, when we are using it.remove() (here it is reference for iterator), then it will not throw exception. Here the iterator itself gets modified.
One diff is that underlying array in ArrayList is not declared volatile where as in CopyOnWriteArrayList underlying object array is declared volatile.
Am not getting concurrent modification exception and am able to change the element and remove the same from the map/concurrentHashMap while inside Iterator?? Can you have a look?
public class ConcurrentHM {
public static void main(String[] args) {
Map map= new HashMap();
map.put(“1”, “1”);
map.put(“2”, “1”);
map.put(“3”, “1”);
map.put(“4”, “1”);
map.put(“5”, “1”);
map.put(“6”, “1”);
Iterator it = map.keySet().iterator();
System.out.println(“HashMap befor iterator: “+map);
while(it.hasNext()){
String key = it.next();
if(key.equals(“4”))
map.remove(key);
}
System.out.println(“HashMap after iterator: “+map);
map= new ConcurrentHashMap();
map.put(“1”, “1”);
map.put(“2”, “1”);
map.put(“3”, “1”);
map.put(“4”, “1”);
map.put(“5”, “1”);
map.put(“6”, “1”);
Iterator it1 = map.keySet().iterator();
System.out.println(“ConcurremntHashMap befor iterator: “+map);
while(it1.hasNext()){
String key = it1.next();
if(key.equals(“4”)){
map.remove(key);
}
}
System.out.println(“ConcurremntHashMap after iterator: “+map);
}
}
Output :
HashMap befor iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1}
HashMap after iterator: {3=1, 2=1, 1=1, 6=1, 5=1}
ConcurremntHashMap befor iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1}
ConcurremntHashMap after iterator: {1=1, 5=1, 6=1, 3=1, 2=1}
Thanks
there could be chance because what ever the key you are removing from map is the last element ,so there is chance get call map.next()
Basically, Map will allow adding/removing elements during Iteration. The Concurrent Modification exception will be thrown only Iterating and Modifying the List and Set. Better read about Iterator and its implementations. Happy learning 😉
This is not correct. You will get concurrent.modification.exception in case of Hashmap.
Hai Pankaj
I cannot understand internal implementaion of below code
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
As you said modCount is the ArrayList variable that holds the modification count and every time we use add, remove or trimToSize method, it increments. expectedModCount is the iterator variable that is initialized when we create iterator with same value as modCount.
My Question is what is the initial value of at first time of modcount and expectedModcounttime and at when level the exception is thrown. i cannot understand can u please explain briefly.
the value of the expectedModCount and modCount should the samme before we start iteration over list.
since each time after modification arraylist increments modCount by 1. – modCount and expectedModCount becomes un equal. so exception gets raised
List list = new ArrayList();
list.add(“1”);
list.add(“2”);
Iterator it2=list.iterator();
while(it2.hasNext()){
String hh=(String)it2.next();
if(hh.equals(“1”)){
list.remove(0);
}
}
System.out.println(list);
after list.remove(0) size of list is 1,so loop will stop
Nice explained..well done pankaj.
Thanks Sambhu
Shouldn’t you pass “5” into the arraylist constructor to avoid java defaulting creating arraylist of size 10?
Yes we can provide that, but it’s an example so I prefer to keep it simple. In real life scenarios, where we want optimization and performance specifying list capacity is beneficial.
Hi,
I want to know if employee class same example instead of String class how can get exception
ConcurrentModificationException.
change the object type in the list and add some values while iterating.
public class Test {
public static void main(String[] args) {
List al=new ArrayList();
Employee ee=new Employee(1,”anoj”);
Employee ee1=new Employee(2,”hai”);
al.add(ee);
al.add(ee1);
Iterator it=al.iterator();
while(it.hasNext()){
Employee hh=(Employee)it.next();
if(hh.getName().equals(“anoj”)){
al.remove(0);
System.out.println(al);
}
}
}}
but i didn’t get ConcurrentModificationException.
u dint get error for this bcoz,
ur deleting 1 object from content of 2 objects thats y there is no more objects to read 2 nd time in hasNext()..
try to add another object after removing object..
u ll get error..
Explanation given is wrong …
package com.Ikeacommon.generics;
import java.util.ArrayList;
import java.util.*;
import java.io.*;
public class ConcurrentModification {
public static void main(String[] args) {
List l = new ArrayList();
l.add(12);
l.add(13);
l.add(15);
l.add(130);
l.add(483);
Iterator it=l.iterator();
System.out.println(“before remove method :”+l);
while (it.hasNext()){
int i=it.next();
if(i==130){l.remove(3);}
System.out.println(i);
//it.remove();
}
System.out.println(“After remove method:”+l);
}}
See here I am removing the 4th element ..after loop continues and read 5th element ..still no Concurrent Modification Exception….
Do following:
use generics
think what’s happening in l.remove(3) statement
print the list size after the while loop. You should have your answer by this time…
You are performing operation: remove
if(i==130){l.remove(3);}
Now if you look there is no element “3” in your list. Remove method a particular object not from a particular index. So try to remove “130” or some other element which list ‘contains’.
HI ANEK SINGH ,
Instead of if(i==130){l.remove(3);} , if I have l.remove(i) , then it’s throwing an exception.
But I didn;t understand why it’s not throwing an exception if we gave index.
Regards
Rani
if you try l.remove(i) then it will throw java.lang.IndexOutOfBoundsException