The CopyOnWriteArrayList
is the thread-safe implementation of the List
interface. CopyOnWriteArrayList is very useful when we want to iterate over a list in a thread-safe way without explicit synchronization.
Key Properties of CopyOnWriteArrayList
While it provides thread safety, it is comparatively slower as compared to ArrayList especially when you're making a lot of modifications to the list.
Let us look into the following example:
public class _4a_ConcurrentModificationException {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Guava");
list.add("Grapes");
for (String value: list) {
if (value.equals("Banana")) {
list.remove("Grapes"); // ConcurrentModificationException
}
}
System.out.println(list);
}
}
Notice that in the above program, we are modifying the list while iterating hence the application will throw ConcurrentModificationException
.
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
at list.arraylist._4a_ConcurrentModificationException.main(_4a_ConcurrentModificationException.java:15)
To avoid this exception, we can either call the remove()
method on an iterator or use CopyOnWriteArrayList
.
The CopyOnWriteArrayList
class makes a fresh copy of the underlying array while performing mutative operations (such as add
, set
, and remove
).
public class _4b_CopyOnWriteArrayList {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Guava");
list.add("Grapes");
for (String value : list) {
if (value.equals("Banana")) {
list.remove("Grapes");
}
}
System.out.println(list);
}
}