Friday, January 1, 2021

Difference Between ArrayList And CopyOnWriteArrayList in Java

CopyOnWriteArrayList was added in Java 5 as a thread-safe alternative to ArrayList, which is one of the most used collection along with HashMap. In this post we'll see the differences between the CopyOnWriteArrayList and ArrayList in Java.

ArrayList Vs CopyOnWriteArrayList in Java

  1. First and foremost difference between CopyOnWriteArrayList and ArrayList is of course thread safety. ArrayList is not thread-safe whereas CopyOnWriteArrayList is thread-safe and fit for use in multi-threaded environment.

    This thread safety in CopyOnWriteArrayList is achieved by making a fresh copy of the underlying array with every mutative operations (add, set, and so on).

  2. Iterator returned by ArrayList is fail-fast. Which means, if the underlying collection is structurally modified in any way except through the iterator's own remove or add methods, it will throw ConcurrentModificationException.

    Iterator returned by CopyOnWriteArrayList is fail-safe. Iterators for the CopyOnWriteArrayList uses a reference to the state of the array at the point that the iterator was created. Since any mutation will result in a fresh copy of the underlying array. Thus the array that the iterator has a reference to never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException.

    Let's see this difference with an example, here we'll have an ArrayList which will be iterated. Simultaneously a new thread is created which will try to add an element to that ArrayList.

    public class CADemo {
      public static void main(String[] args) {
        List<Integer> numList = new ArrayList<Integer>();
        // Adding 5 elements to the set
        for(int i=1;i<=5;i++) {
          numList.add(i);
        }
            
        // Creating new thread
        new Thread(new Runnable(){
          @Override
          public void run() {
            try {
              // introducing some delay
              Thread.sleep(150);
            } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
            }
            // add new element to the set
            numList.add(6);
            System.out.println("" + numList);
          }
        }).start();
                    
        // get an iterator
        Iterator<Integer> itr = numList.iterator();
        while(itr.hasNext()){
          Integer i = itr.next();
          try {
            Thread.sleep(30);
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
          //itr.remove();
          System.out.println("" + i);
        }
      }
    }
    

    Output

    1
    2
    3
    4
    5
    [6]
    Exception in thread "main" java.util.ConcurrentModificationException
     at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
     at java.util.ArrayList$Itr.next(Unknown Source)
     at org.netjs.prgrm.CADemo.main(CADemo.java:37)
    

    Here it can be seen that the ConcurrentModificationException is thrown as there is an attempt to add an element to the ArrayList while it is iterated.

    Example code with CopyOnWriteArrayList

    Now let's changed the ArrayList with CopyOnWriteArrayList.

    public class CADemo {
      public static void main(String[] args) {
        List<Integer> numList = new CopyOnWriteArrayList<Integer>();
        // Adding 5 elements to the set
        for(int i=1;i<=5;i++) {
          numList.add(i);
        }
            
        // Creating new thread
        new Thread(new Runnable(){
          @Override
          public void run() {
            try {
              // introducing some delay
              Thread.sleep(150);
            } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
            }
            // add new element to the set
            numList.add(6);
            System.out.println("" + numList);
          }
        }).start();
            
            
        // get an iterator
        Iterator<Integer> itr = numList.iterator();
        while(itr.hasNext()){
          Integer i = itr.next();
          try {
            Thread.sleep(30);
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
          //itr.remove();
          System.out.println("" + i);
        }
      }
    }
    

    Output

    1
    2
    3
    4
    [1, 2, 3, 4, 5, 6]
    5
    

    Here it can be seen that the ConcurrentModificationException is not thrown. Also, since iterator gets its own copy so it doesn't reflect the change made to the CopyOnWriteArrayList while iteration is done.

  3. Performance wise ArrayList is faster as it is not synchronized and there is no added burden of thread-safety. CopyOnWriteArrayList is comparatively slower and if there are lots of writes by various threads that will degrade the performance of the CopyOnwriteArrayList as there will be copies made per mutation.

That's all for this topic Difference Between ArrayList And CopyOnWriteArrayList in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between HashMap And ConcurrentHashMap in Java
  2. Difference Between CountDownLatch And CyclicBarrier in Java
  3. Difference Between ReentrantLock and Synchronized in Java
  4. CopyOnWriteArraySet in Java With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. How to Loop or Iterate an Arraylist in Java
  2. How to Join Lists in Java
  3. Fail-Fast Vs Fail-Safe Iterator in Java
  4. Java BlockingQueue With Examples
  5. Lambda Expressions in Java 8
  6. Race Condition in Java Multi-Threading
  7. Deadlock in Java Multi-Threading
  8. Java Pass by Value or Pass by Reference