Java 5 – CopyOnWriteArrayList class

In this article, we will discuss CopyOnWriteArrayList class – the implementation class for List interface in detail

This is the thread-safe version of ArrayList, where modify operation is performed on a separate cloned copy and finally JVM merges both original and cloned copies

Apart from thread-safety difference between ArrayList and CopyOnWriteArrayList, all properties of ArrayList are applicable to CopyOnWriteArrayList

1. CopyOnWriteArrayList:

  • CopyOnWriteArrayList is implementation class of List interface (i.e.; CopyOnWriteArrayList implements List)
  • For every modify/update operation, a new separate cloned copy is created and modification is performed on cloned copy; while other threads can iterate over original copy
  • After modification/updation, JVM takes care of merging both copies (i.e.; original and cloned copy) –> so that we get latest copy with all updation/modification
  • Since, every time a new separate cloned copy is created for updation/modification. Therefore, it is suited for multi-threaded environment where there are more number of read/get operation and comparatively less update/modify operation
  • While one thread iterating over original copy, other threads can modify with separate cloned copy and compiler won’t throw any ConcurrentModificationException; which isn’t case with ArrayList
  • It never throws ConcurrentModificationException while 2 or more threads operating simultaneously i.e.; it is fail-safe iterator
  • But, there are certain limitation too with CopyOnWriteArrayList which isn’t case with ArrayList like, while iterating CopyOnWriteArrayList, remove operation isn’t possible and compiler throws UnsupportedOperationException
  • Other than above discussed points, all other properties of ArrayList are applicable for CopyOnWriteArrayList too i.e.;
  • Insertion-order is maintained
  • Duplicate objects are allowed
  • Null insertion is possible
  • This is introduced in Java 1.5 version
  • Present in java.util.concurrent package and implements java.util.List
  • Also, implements java.util.RandomAccess, java.lang.Cloneable, java.io.Serializable marker interfaces which provides special ability to CopyOnWriteArrayList (provided by JVM at run time) like,
  • java.util.RandomAccess: to access any random element/objects with same speed
  • java.lang.Cloneable: to create a duplicate object or to clone an object
  • java.io.Serializable: to transfer objects across network
7-copyonwritearraylist-in-java

Source: Team BenchResources.Net

2. CopyOnWriteArrayList constructors:

2.1 CopyOnWriteArrayList cowal = new CopyOnWriteArrayList();

  • creates an empty CopyOnWriteArrayList object

2.2 CopyOnWriteArrayList cowal = new CopyOnWriteArrayList(Collection c);

  • creates an equivalent CopyOnWriteArrayList object for the specified collection
  • it is basically used for inter-conversion between collection objects

2.3 CopyOnWriteArrayList cowal = new CopyOnWriteArrayList(Object[] a);

  • creates an equivalent CopyOnWriteArrayList object for the specified Object array

3. CopyOnWriteArrayList method:

CopyOnWriteArrayList methodDescription
boolean addIfAbsent(Object o);to add a new object to CopyOnWriteArrayList, if specified object isn’t present in the invoking list
int addAllAbsent(Collection c);to add all objects in the specified collection; only if it is not present in the invoking list

Note: Apart from above mentioned CopyOnWriteArrayList specific methods, CopyOnWriteArrayList class inherits all methods from List interface

4. CopyOnWriteArrayList Examples:

  1. Using addAllAbsent() method
  2. Using combination of addAll() and addAllAbsent() methods

4.1 CopyOnWriteArrayList :

CopyOnWriteArrayListDemo.java

package in.bench.resources.concurrent.collection;

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

public class CopyOnWriteArrayListDemo {

	public static void main(String[] args) {

		// COWAL of All capital
		CopyOnWriteArrayList<String> allCapital =
				new CopyOnWriteArrayList<String>();
		allCapital.addIfAbsent("Berlin");
		allCapital.addIfAbsent("Tokyo");
		allCapital.addIfAbsent("Moscow");
		allCapital.addIfAbsent("Tokyo");// again, adding Tokyo

		// AL of European capital
		ArrayList<String> euroCapital = new ArrayList<String>();
		euroCapital.add("Moscow");
		euroCapital.add("London");
		euroCapital.add("Paris");

		// adding European capital to all capital using addAllAbsent()
		allCapital.addAllAbsent(euroCapital);

		// print to console
		System.out.println(allCapital);
	}
}

Output:

[Berlin, Tokyo, Moscow, London, Paris]

Explanation:

  • 1st list is of type CopyOnWriteArratList which uses addIfAbsent() method to add new elements; only if it isn’t already present in the invoking list (i.e.; COWAL)
  • From above output, it is clear though Tokyo is added 2nd time using addIfAbsent() method and it isn’t get added to list
  • 2nd list of type ArrayList which is general one and adds new elements using add() method
  • There is one final operation being performed in the above demo example; which is adding all elements of ArrayList to CopyOnWriteArrayList using addAllAbsent() method
  • Which checks in the invoking COWAL list before adding any elements from specified AL list
  • From the output, it is clear that Moscow is already present so it isn’t added to the invoking list

4.2 CopyOnWriteArrayList :

CopyOnWriteArrayListExample.java

package in.bench.resources.concurrent.collection;

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

public class CopyOnWriteArrayListExample {

	public static void main(String[] args) {

		// AL of European capital
		ArrayList<String> euroCapital = new ArrayList<String>();
		euroCapital.add("Moscow");
		euroCapital.add("London");
		euroCapital.add("Paris");

		// AL of Asian capital
		ArrayList<String> asiaCapital = new ArrayList<String>();
		asiaCapital.add("Tokyo");
		asiaCapital.add("Beijing");
		asiaCapital.add("Singapore");

		// COWAL of All capital
		CopyOnWriteArrayList<String> allCapital =
				new CopyOnWriteArrayList<String>();
		allCapital.add("Berlin");
		allCapital.add("Tokyo");
		allCapital.add("Moscow");

		// adding European capital to all capital using addAll()
		allCapital.addAll(euroCapital);

		// print to console
		System.out.println(allCapital);

		// adding Asian capital to all capital using addAllAbsent()
		allCapital.addAllAbsent(asiaCapital);

		// print to console
		System.out.println(allCapital);
	}
}

Output:

[Berlin, Tokyo, Moscow, Moscow, London, Paris]
[Berlin, Tokyo, Moscow, Moscow, London, Paris, Beijing, Singapore]

Explanation:

  • We have created 2 ArrayList objects of European capitals and Asian capitals
  • And also created all mix of capitals of type CopyOnWriteArrayList object
  • 1st operation: adding ArrayList to CopyOnWriteArrayList using addAll(Collection) method
  • This operation is performed without checking already elements present in the specified list with the invoking list
  • As a result, there are duplicates elements in the invoking list after add operation
  • From the output, it is seen that there are 2 Moscow elements (i.e.; Moscow present in both specified list and invoking list)
  • 2nd operation: adding ArrayList to CopyOnWriteArrayList using addAllAbsent(Collection) method
  • This operation is performed after checking invoking list with the specified liste.; if the invoking list already contains any of elements present in the specified list then it is neglected and rest all are added to invoking list
  • From the output, it is clear that Tokyo doesn’t get added to the invoking list as it is already present

Related Articles:

References:

Happy Coding !!
Happy Learning !!

Java 5- CopyOnWriteArrayList with Read and Update operations simultaneously
Java 5 - ConcurrentHashMap v/s SynchronizedMap