CopyOnWriteArrayList in Java

CopyOnWriteArrayList Class Overview

In this article, we’ll be looking at the CopyOnWriteArrayList from the java.util.concurrent package.
This is a very useful construct in the multi-threaded programs – when we want to iterate over a list in a thread-safe way without an explicit synchronization.
A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array. 
Normally CopyOnWriteArrayList is very expensive because it involves costly Array copy with every writes operation but it's very efficient if you have a List where Iteration outnumbers mutation e.g. you mostly need to iterate the ArrayList and don't modify it too often.

What will we learn?

  1. Summary of CopyOnWriteArrayList Class Constructors
  2. Summary of CopyOnWriteArrayList Class Methods
  3. CopyOnWriteArrayList Class Examples

1. Summary of CopyOnWriteArrayList Class Constructors

  • CopyOnWriteArrayList() - Creates an empty list.
  • CopyOnWriteArrayList(Collection<? extends E> c) - Creates a list containing the elements of the specified collection, in the order, they are returned by the collection's iterator.
  • CopyOnWriteArrayList(E[] toCopyIn) - Creates a list holding a copy of the given array.

2. Summary of CopyOnWriteArrayList Class Methods

Below class, diagram shows a list of CopyOnWriteArrayList Class methods. 
Read more about CopyOnWriteArrayList Class Methods on CopyOnWriteArrayList Javadoc 8

3. CopyOnWriteArrayList Class Examples

ConcurrentModificationException Example

As we know that Iterator of CopyOnWriteArrayList is fail-safe and doesn't throw ConcurrentModificationException. Let's demonstrates this by examples. 
Let's first demonstrates iterator of ArrayList is a fail-fast and throw ConcurrentModificationException with an example:
public class CopyOnWriteArrayListExample {

        private static List<Integer> list = new ArrayList<>();
        public static void main(final String[] args) {
           list.add(1);
           list.add(2);
           list.add(3);
  
           final Runnable runnable = () -> {
               list.add(4);
               list.add(5);
           };
  
          final Thread thread = new Thread(runnable);
          thread.start();
  
          final Iterator<Integer> iterator = list.iterator();
          while (iterator.hasNext()) {
              final Integer integer = iterator.next();
              System.out.println(integer);
          }
      }
}
Output:
1
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 com.javaguides.collections.specialpurposeimpl.CopyOnWriteArrayListExample
.main(CopyOnWriteArrayListExample.java:33)
Note that in the above example, we were modified ArrayList via creating a separate thread.
Now, let's replace ArrayList with CopyOnWriteArrayList class and see the output. 
Here is the source code:
/**
 *
 * This program demonstrates how CopyOnWriteArrayList works.
 *
 * @author www.javaguides.net
 */

public class CopyOnWriteArrayListExample {

         private static List<Integer> list = new CopyOnWriteArrayList<>();
         public static void main(final String[] args) {
           list.add(1);
           list.add(2);
           list.add(3);
  
           final Runnable runnable = () -> {
               list.add(4);
               list.add(5);
           };
  
          final Thread thread = new Thread(runnable);
          thread.start();
  
          final Iterator<Integer> iterator = list.iterator();
          while (iterator.hasNext()) {
              final Integer integer = iterator.next();
              System.out.println(integer);
          }
      }
}
Output:
1
2
3
4
5
Note that iterator of CopyOnWriteArrayList is fail-safe and doesn't throw ConcurrentModificationException.

Removing While Iterating is Not Allowed

The CopyOnWriteArrayList was created to allow for the possibility of safe iterating over elements even when the underlying list gets modified.
Because of the copying mechanism, the remove() operation on the returned Iterator is not permitted – resulting with UnsupportedOperationException:
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 *
 * This program demonstrates how CopyOnWriteArrayList works.
 *
 * @author www.javaguides.net
 */

public class CopyOnWriteArrayListExample {

      private static List<Integer> list = new CopyOnWriteArrayList<>();
      public static void main(final String[] args) {
          list.add(1);
          list.add(2);
          list.add(3);
  
          final Iterator<Integer> iterator = list.iterator();
          while (iterator.hasNext()) {
               final Integer integer = iterator.next();
               iterator.remove();
               System.out.println(integer);
          }
      }
}
Output:
Exception in thread "main" java.lang.UnsupportedOperationException
 at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(CopyOnWriteArrayList.java:1178)
 at com.javaguides.collections.specialpurposeimpl.CopyOnWriteArrayListExample.
main(CopyOnWriteArrayListExample.java:25)

Comments