CopyOnWriteArrayList in Java

In this article, we will learn about CopyOnWriteArrayList class from collections framework with examples.

CopyOnWriteArrayList Class Overview

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. 

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)

Related Collections Examples

Free Spring Boot Tutorial | Full In-depth Course | Learn Spring Boot in 10 Hours


Watch this course on YouTube at Spring Boot Tutorial | Fee 10 Hours Full Course