CopyOnWriteArraySet in Java

CopyOnWriteArraySet Class Overview

In this article, we’ll discuss about CopyOnWriteArraySet from the java.util.concurrent package.
This is a very useful construct in the multi-threaded programs – when we want to iterate over a set in a thread-safe way without an explicit synchronization.
A CopyOnWriteArraySet that uses an internal CopyOnWriteArrayList for all of its operations. Thus, it shares the same basic properties:
  • It is best suited for applications in which set sizes generally stay small, read-only operations vastly outnumber mutative operations, and you need to prevent interference among threads during traversal.
  • It is thread-safe.
  • Mutative operations (add, set, remove, etc.) are expensive since they usually entail copying the entire underlying array.
  • Iterators do not support the mutative remove operation.
  • Traversal via iterators is fast and cannot encounter interference from other threads. Iterators rely on unchanging snapshots of the array at the time the iterators were constructed.
CopyOnWriteArraySet class is a member of Java Collections Framework

What will we Learn?

  1. CopyOnWriteArraySet Class Constructor Summary
  2. CopyOnWriteArraySet Class Method Summary
  3. CopyOnWriteArraySet Class Examples

1. CopyOnWriteArraySet Class Constructor Summary

  • CopyOnWriteArraySet() - Creates an empty set.
  • CopyOnWriteArraySet(Collection<? extends E> c) - Creates a set containing all of the elements of the specified collection.

2. CopyOnWriteArraySet Class Method Summary

  • boolean add(E e) - Adds the specified element to this set if it is not already present.
  • boolean addAll(Collection<? extends E> c) - Adds all of the elements in the specified collection to this set if they're not already present.
  • void clear() - Removes all of the elements from this set.
  • boolean contains(Object o) - Returns true if this set contains the specified element.
  • boolean containsAll(Collection<?> c) - Returns true if this set contains all of the elements of the specified collection.
  • boolean equals(Object o) - Compares the specified object with this set for equality.
  • void forEach(Consumer<? super E> action) - Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.
  • boolean isEmpty() - Returns true if this set contains no elements.
  • Iterator iterator() - Returns an iterator over the elements contained in this set in the order in which these elements were added.
  • boolean remove(Object o) - Removes the specified element from this set if it is present.
  • boolean removeAll(Collection<?> c) - Removes from this set all of its elements that are contained in the specified collection.
  • boolean removeIf(Predicate<? super E> filter) - Removes all of the elements of this collection that satisfy the given predicate.
  • boolean retainAll(Collection<?> c) - Retains only the elements in this set that are contained in the specified collection.
  • int size() - Returns the number of elements in this set.
  • Spliterator spliterator() - Returns a Spliterator over the elements in this set in the order in which these elements were added.
  • Object[] toArray() - Returns an array containing all of the elements in this set.
  • T[] toArray(T[] a) - Returns an array containing all of the elements in this set; the runtime type of the returned array is that of the specified array

3. CopyOnWriteArraySet Class Examples

Let's look at simple example to demonstrates how to use
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * This program demonstrates how a CopyOnWriteArraySet works in multi-threading
 * context.
 *
 * @author www.javaguides.net
 */

public class CopyOnWriteArraySetExample {

    public static void main(final String[] args) {

       final CopyOnWriteArraySet<Integer> set = new CopyOnWriteArraySet<>();

       set.add(1);
       set.add(2);
       set.add(3);
       set.add(4);
       set.add(5);

       final Runnable runnable = () -> {
             set.add(4);
             set.add(5);
       };
  
       final Thread thread = new Thread(runnable);
       thread.start();
  
       final Iterator<Integer> iterator = set.iterator();
       while (iterator.hasNext()) {
             final Integer integer = iterator.next();
             System.out.println(integer);
       }
   }
}
Output:
1
2
3
4
5
One more example from JavaDoc: The following code sketch uses a copy-on-write set to maintain a set of Handler objects that perform some action upon state updates.
class Handler {
    void handle() {

    };
}

class X {
      private final CopyOnWriteArraySet<Handler> handlers = new CopyOnWriteArraySet<Handler>();

      public void addHandler(final Handler h) {
         handlers.add(h);
      }

      private long internalState;

      private synchronized void changeState() {
           internalState = 10;
      }

      public void update() {
          changeState();
          for (final Handler handler : handlers)
              handler.handle();
      }
}     

Removing While Iterating is Not Allowed

It's important to know about iterators of this collection class doesn't support remove() operation, trying to remove an element while iterating will result in UnSupportedOperationException.
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * This program demonstrates how a CopyOnWriteArraySet works in multi-threading
 * context.
 *
 * @author www.javaguides.net
 */

public class CopyOnWriteArraySetExample {

       public static void main(final String[] args) {

       final CopyOnWriteArraySet<Integer> set = new CopyOnWriteArraySet<>();

       set.add(1);
       set.add(2);
       set.add(3);
       set.add(4);
       set.add(5);

       final Runnable runnable = () -> {
            set.add(4);
            set.add(5);
       };
  
       final Thread thread = new Thread(runnable);
       thread.start();
  
       final Iterator<Integer> iterator = set.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.CopyOnWriteArraySetExample
.main(CopyOnWriteArraySetExample.java:36)

Comments