CopyOnWriteArrayList In Java

CopyOnWriteArrayList In Java | It is a thread-safe version of ArrayList. As the name indicates CopyOnWriteArrayList creates a cloned copy of the underlying ArrayList for every update operation at a certain point both will synchronize automatically which is taken care by JVM internally.

  1. As the update operation will be performed on a cloned copy therefore there is no effect for the threads which performs read operations.
  2. It is costly to use because for every update operation a cloned copy will be created. Hence CopyOnWriteArrayList is the best choice if several read operations and fewer write operations are required.
  3. Insertion order is preserved.
  4. Duplicate objects are allowed.
  5. Heterogeneous objects are allowed.
  6. Null insertion is possible.
  7. It implements Serializable, Clonable, and RandomAccess Interfaces.
  8. While one thread iterates CopyOnArrayList, the other threads are allowed to modify and we won’t get ConcurrentModificationException. The iterator is fail-safe.
  9. The Iterator of ArrayList can perform the remove operation but the Iterator of CopyOnWriteArrayList can’t perform the remove operation. Otherwise, it throws UnsupportedOperationException.

Constructors of CopyOnWriteArrayList

  1. CopyOnWriteArrayList();
  2. CopyOnWriteArrayList(Collection c);
  3. CopyOnWriteArrayList(Object[] a);

CopyOnWriteArrayList.addIfAbsent() Method in Java

boolean addIfAbsent(Object o):- The element will be added if and only if the List doesn’t contain this Element.

import java.util.concurrent.CopyOnWriteArrayList;

public class Test {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> cowal = new CopyOnWriteArrayList<String>();
        cowal.add("A");
        cowal.add("A");
        System.out.println(cowal); // [A, A]
        
        System.out.println(cowal.addIfAbsent("B")); // true
        System.out.println(cowal); // [A, A, B]
        
        System.out.println(cowal.addIfAbsent("A")); // false
        System.out.println(cowal); // [A, A, B]
    }
}

Output:-

CopyOnWriteArrayList.addAllAbsent() Method in Java

int addAllAbsent(Collection c):- The elements of Collection will be added to the List if elements are absent and returns the number of elements added.

import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();
        al.add("A");
        al.add("B");

        CopyOnWriteArrayList<String> cal = new CopyOnWriteArrayList<String>();
        cal.add("A");
        cal.add("C");
        cal.addAll(al);
        System.out.println(cal); // [A, B, A, C]

        ArrayList<String> al2 = new ArrayList<String>();
        al2.add("A");
        al2.add("D");

        System.out.println(cal.addAllAbsent(al2));
        /*
         * From al2, “A” is already available in cal but “D” is not present in cal
         */
        System.out.println(cal); // [A, B, A, C, D]
    }
}

Output:-

CopyOnWriteArrayList Examples in Java

Example-1

import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();
        al.add("A");
        al.add("B");

        CopyOnWriteArrayList<String> cal = new CopyOnWriteArrayList<String>();
        cal.addIfAbsent("A");
        cal.addIfAbsent("C");
        cal.addAll(al);
        System.out.println(cal); // [A, C, A, B]

        ArrayList<String> al2 = new ArrayList<String>();
        al2.add("A");
        al2.add("E");

        System.out.println(cal.addAllAbsent(al2));
        System.out.println(cal); // [A, C, A, B, E]
    }
}

Output:-

Example-2

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

public class MyThread extends Thread {

    static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();

    public void run() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ie) {
        }
        System.out.println("Child thread updating list");
        list.add("Z");
    }

    public static void main(String[] args) throws Exception {
        list.add("A");
        list.add("B");
        list.add("C");

        // create another thread
        MyThread mt = new MyThread();
        mt.start();

        // iterate list
        Iterator<String> itr = list.iterator();
        while (itr.hasNext()) {
            String str = (String) itr.next();
            System.out.println("Main thread iterating" 
                 + " list & current object is: " + str);
            Thread.sleep(3000);
        }
        System.out.println(list);
    }
}

Output:-

In the above example, while the main thread iterating the List, the child thread is allowed to modify and we won’t get any ConcurrentModificationException.

  • If we replace CopyOnWriteArrayList with ArrayList then we will get ConcurrentModificationException.
  • The iterator of CopyOnWriteArrayList can’t perform remove operation otherwise we will get RuntimeException: UnsupportedOperationException.

Example-3

If it is a normal ArrayList iterator then it can perform both read and remove operations. But the CopyOnWriteArrayList iterator can perform only read operation but not remove operation else we will get UnsupportedOperationException.

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

public class Test {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> cal = new CopyOnWriteArrayList<String>();
        cal.add("A");
        cal.add("B");
        cal.add("C");
        System.out.println(cal); // [A, B, C]

        Iterator<String> itr = cal.iterator();
        while (itr.hasNext()) {
            String str = (String) itr.next();
            if (str.equals("C"))
                itr.remove();
        }
        System.out.println(cal);
    }
}

Output:-

In the above program if we replace CopyOnWriteArrayList with ArrayList then we won’t get any Exception. In this case, the output is:-

Example-4

Adding after iterator,

    import java.util.Iterator;
    import java.util.concurrent.CopyOnWriteArrayList;
    
    public class Test {
        public static void main(String[] args) {
            CopyOnWriteArrayList<String> cal = new CopyOnWriteArrayList<String>();
            cal.add("A");
            cal.add("B");
            cal.add("C");
            System.out.println(cal); // [A, B, C]
    
            Iterator<String> itr = cal.iterator();
            cal.add("D"); // add element
            while (itr.hasNext()) {
                String str = (String) itr.next();
                System.out.println(str);
            }
        }
    }

    Output:-

    Reason:-

    • Every update operation will be performed on a separate copy hence after getting an iterator if we are trying to perform any modification to the List it won’t be reflected in the iterator.
    • In the above program if we replace CopyOnWriteArrayList with ArrayList then we will get ConcurrentModificationException.

    Output:-

    Difference between ArrayList and CopyOnWriteArrayList

    ArrayListCopyOnWriteArrayList
    It is not thread-safe.It is thread-safe because every update operation will be performed on a separate cloned copy.
    While one thread iterates the List object, the other threads are not allowed to modify the List otherwise we will get ConcurrentModificationException.While one thread iterates the List object, the other threads are allowed to modify the List object in a safe manner and we will not get ConcurrentModificationException.
    The iterator is fail-fast.The iterator is fail-safe.
    The iterator of ArrayList can perform both read and remove operations.The iterator of CopyOnWriteArrayList can perform only the read operation but not the remove operation otherwise we will get: UnsupportedOperationException.
    It was introduced in the 1.2 version.It was introduced in the 1.5 version.
    It is present in java.util package.It is present in java.util.concurrent package.

    Difference between CopyOnWriteArrayList, synchronizedList() and Vector

    CopyOnWriteArrayListsynchronizedList()Vector
    We will get thread safety because every update operation will be performed on a separate cloned copy.We will get thread safety because at a time the List can be accessed by only one thread.We will get thread safety because at a time Vector can be accessed by only one thread.
    At a time multiple threads are allowed to access/operate on CopyOnWriteArrayList.At a time only one thread is allowed to access/operate on the List object.At a time only one thread is allowed to access/operate on the Vector object.
    While one thread iterates the List object, other threads are allowed to modify and it won’t throw ConcurrentModificationException.While one thread iterates, the other threads are not allowed to modify the List otherwise it throws ConcurrentModificationException.While one thread iterating, the other threads are not allowed to modify the List otherwise it throws ConcurrentModificationException.
    Iterator is fail-safe and won’t raise ConcurrentModificationException.Iterator is fail-fast and it will raise ConcurrentModificationException.Iterator is fail-fast and it will raise ConcurrentModificationException.
    Iterator can’t perform remove operation otherwise we will get UnsupportedOperationException. Iterator can perform remove operation.Iterator can perform remove operation.
    It was introduced in the 1.5 version.It was introduced in the 1.2 version.It was introduced in the 1.0 version.

    If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!

    Leave a Comment

    Your email address will not be published. Required fields are marked *