Java CopyOnWriteArraySet With Examples

CopyOnWriteArraySet in Java extends the AbstractSet which in turn implements the Set interface and is part of java.util.concurrent package. How CopyOnWriteArraySet differs from other Set implementations in Java Collections framework is that it is thread-safe.

CopyOnWriteArraySet internal implementation in Java

CopyOnWriteArraySet internally uses CopyOnWriteArrayList for all of its operations and shares the same basic properties. With in the CopyOnWriteArraySet class in Java a CopyOnWriteArrayList is defined as follows-

private final CopyOnWriteArrayList<E> al;

When a CopyOnwriteArraySet is created this CopyOnWriteArrayList field is initialized and used for storing elements.

For example when a CopyOnwriteArraySet is created using a constructor with no-args.

public CopyOnWriteArraySet() {
  al = new CopyOnWriteArrayList<E>();
}

Features of the CopyOnWriteArraySet

Some of the features of the CopyOnWriteArraySet in Java discussed in this post are-

  1. CopyOnWriteArraySet is a Set implementation so duplicate elements are not allowed.
  2. CopyOnWriteArraySet is thread-safe.
  3. Since CopyOnWriteArraySet internally uses CopyOnWriteArrayList so just like in CopyOnWriteArrayList all mutative operations (add, set, and so on) create a separate copy of the underlying array so that there is no thread interference.
  4. Iterator returned by CopyOnWriteArraySet in Java is fail-safe which means iterator is guaranteed not to throw ConcurrentModificationException even if the Set is structurally modified at any time after the iterator is created.
  5. Iterator’s element changing operations like add, remove are not supported and throw UnsupportedOperationException.

Java CopyOnWriteArraySet constructors

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

Java example creating a CopyOnWriteArraySet

Here is a simple example showing how to create CopyOnWriteArraySet and add elements to it.

public class ConcurrentSet {
  public static void main(String[] args) {
    Set<String> carSet = new CopyOnWriteArraySet<String>();
    carSet.add("Audi");
    carSet.add("Jaguar");
    carSet.add("BMW");
    carSet.add("Mini Cooper");
    carSet.add("BMW");
    carSet.add(null);
    for(String car : carSet) {
      System.out.println("Car- " + car);
    }
  }
}
Output
Car- Audi
Car- Jaguar
Car- BMW
Car- Mini Cooper
Car- null

As you can see from the output duplicates are not allowed in CopyOnWriteArraySet even if “BMW” was added twice it’s stored only once. Also one null value is allowed.

CopyOnWriteArraySet returns a fail-safe iterator

Iterator returned by CopyOnWriteArraySet in Java is fail-safe which means iterator is guaranteed not to throw ConcurrentModificationException even if the Set is structurally modified at any time after the iterator is created.

When an iterator is created for the CopyOnWriteArraySet it gets an immutable copy of the underlying array which is iterated. This array never changes during the lifetime of the iterator, so interference is impossible.

But note that since iteration is done on a separate copy so any modification in the CopyOnWriteArraySet won’t be reflected while iteration.

CopyOnWriteArraySet iteration example

Let’s see an example of iteration in CopyOnWriteArraySet. To make it clearer first we’ll iterate a HashSet while it is also modified concurrently by another thread to see what happens in the case of HashSet which has a fail-fast iterator then we’ll see the same example using CopyOnWriteArraySet.

public class SetItr {
  public static void main(String[] args) {
    Set<String> carSet = new HashSet<String>();
    carSet.add("Audi");
    carSet.add("Jaguar");
    carSet.add("BMW");
    carSet.add("Mini Cooper");
    Thread t1 = new Thread(new ItrSet(carSet));
    Thread t2 = new Thread(new ModSet(carSet));
    t1.start();
    t2.start();
    try {
      t1.join();
      t2.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

//Thread class for iteration
class ItrSet implements Runnable{
  Set<String> carSet; 
  public ItrSet(Set<String> carSet){
    this.carSet = carSet;
  }
  @Override
  public void run() {
    Iterator<String> i = carSet.iterator(); 
    while (i.hasNext()){ 
      System.out.println(i.next()); 
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } 
    }     
  }
}

//Thread class for modifying Set
class ModSet implements Runnable{
  Set<String> carSet; 
  public ModSet(Set<String> carSet){
    this.carSet = carSet;
  }
  @Override
  public void run() {
    System.out.println("Adding new value to the Set"); 
    carSet.add("Mercedes");  
  }     
}
Output
Adding new value to the Set
Audi
Exception in thread "Thread-0" java.util.ConcurrentModificationException
	at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1498)
	at java.base/java.util.HashMap$KeyIterator.next(HashMap.java:1521)
	at com.knpcode.ItrSet.run(SetItr.java:40)
	at java.base/java.lang.Thread.run(Thread.java:844)

As you can see ConcurrentModificationException is thrown as structural modification is detected while iterating the HashSet.

Using CopyOnWriteArraySet

By changing the HashSet to the CopyOnWriteArraySet in the same code and running it.

Set<String> carSet = new CopyOnWriteArraySet<String>();

You can get the output as-

Adding new value to the Set
Audi
Jaguar
BMW
Mini Cooper

Now ConcurrentModificationException is not thrown but the new value which is added is not displayed in the iteration as the iteration is done on a separate copy.

Iterator’s add, remove method not permitted in CopyOnWriteArraySet

Since iteration of the elements in CopyOnWriteArraySet is done on a separate copy iterator’s element-changing operations like remove are not supported. These methods throw UnsupportedOperationException.

public class SetItr {
  public static void main(String[] args) {
    Set<String> carSet = new CopyOnWriteArraySet<String>();
    carSet.add("Audi");
    carSet.add("Jaguar");
    carSet.add("BMW");
    carSet.add("Mini Cooper");
    Iterator<String> itr = carSet.iterator(); 
    while (itr.hasNext()){ 
      String str = itr.next();
      if(str.equals("BMW")) {
        // removing using iterator's remove method
        itr.remove();
      }
    }
  }
}
Output
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(CopyOnWriteArrayList.java:1117)
at com.knpcode.SetItr.main(SetItr.java:21)

Important points about CopyOnWriteArraySet

  1. CopyOnWriteArraySet is best suited for applications in which set sizes are small, there are more read-only operations than mutative operations and you need to prevent interference among threads during traversal.
  2. Mutative operations (add, set, remove, etc.) are costly because of the added task of creating copies of the underlying array.
  3. CopyOnWriteArraySet is guaranteed to not throw ConcurrentModificationException even if there are concurrent modifications to the Set while iteration. At the same time iterator’s element-changing operations like remove are not supported.

That's all for the topic Java CopyOnWriteArraySet With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

Java ConcurrentSkipListSet With Examples

ConcurrentSkipListSet in Java is a sorted set just like TreeSet but it is also scalable and concurrent so ConcurrentSkipListSet is thread-safe and can be accessed by multiple threads safely.

In ConcurrentSkipListSet operations like add and remove are done atomically using compare and swap (CAS). These are lock-free so overhead of synchronization is not there.

ConcurrentSkipListSet was added in Java 6 and it is part of java.util.concurrent package.

SkipList data structure

As per https://en.wikipedia.org/wiki/Skip_list - Skip list is a data structure that allows fast search within an ordered sequence of elements. Fast search is made possible by maintaining a linked hierarchy of subsequences, with each successive subsequence skipping over fewer elements than the previous one.

As you can see for faster search skip list requires elements to be in an ordered sequence, that is why elements are sorted in the Java ConcurrentSkipListSet.

Java ConcurrentSkipListSet - A sorted set

ConcurrentSkipListSet class in Java implements NavigableSet interface which in turn extends the SortedSet interface. So, ConcurrentSkipListSet is a sorted set with navigation methods reporting closest matches for given search targets.

The elements of the ConcurrentSkipListSet are kept sorted according to their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.

ConcurrentSkipListSet internal data structure

Just like other Set implementations use the equivalent Map implementation for storing elements, ConcurrentSkipListSet also uses ConcurrentSkipListMap internally. Each constructor of ConcurrentSkipListSet creates an instance of ConcurrentSkipListMap and use that for its operations.

Java ConcurrentSkipListSet constructors

  • ConcurrentSkipListSet()- Constructs a new, empty set that orders its elements according to their natural ordering.
  • ConcurrentSkipListSet(Collection<? extends E> c)- Constructs a new set containing the elements in the specified collection, that orders its elements according to their natural ordering.
  • ConcurrentSkipListSet(Comparator<? super E> comparator)- Constructs a new, empty set that orders its elements according to the specified comparator.
  • ConcurrentSkipListSet(SortedSet s)- Constructs a new set containing the same elements and using the same ordering as the specified sorted set.

ConcurrentSkipListSet Java example

import java.util.Iterator;
import java.util.NavigableSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class SkipSetDemo {
  public static void main(String[] args) {
    NavigableSet<String> carSet = new ConcurrentSkipListSet<String>();
    carSet.add("Audi");
    carSet.add("Jaguar");
    carSet.add("BMW");
    carSet.add("Mini Cooper");
    carSet.add("BMW");
    Iterator<String> itr = carSet.iterator();
    while(itr.hasNext()){
      System.out.println("Value -  " + itr.next());
    }
  }
}
Output
Value -  Audi
Value -  BMW
Value -  Jaguar
Value -  Mini Cooper
Couple of things to note here-
  1. Elements are stored in sorted order.
  2. Even if “BMW” is added twice it’s inserted only once, ConcurrentSkipListSet being a Set implementation doesn’t allow duplicate elements.

Nulls are not allowed in ConcurrentSkipListSet

ConcurrentSkipListSet in Java doesn’t allows null values.

If you add the statement- carSet.add(null); in the previous example it will result in following error.

Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.concurrent.ConcurrentSkipListMap.doPut(ConcurrentSkipListMap.java:597)
at java.base/java.util.concurrent.ConcurrentSkipListMap.putIfAbsent(ConcurrentSkipListMap.java:1788)
at java.base/java.util.concurrent.ConcurrentSkipListSet.add(ConcurrentSkipListSet.java:242)
at com.knpcode.SkipSetDemo.main(SkipSetDemo.java:14)

Navigational methods in ConcurrentSkipListSet example

Since ConcurrentSkipListSet implements NavigableSet interface so it has navigation methods reporting closest matches for given search targets. Here we have an example showing some of the navigation methods.

public class SkipSetDemo {
  public static void main(String[] args) {
    NavigableSet<Integer> numSet = new ConcurrentSkipListSet<Integer>();
    numSet.add(1);
    numSet.add(2);
    numSet.add(5);
    numSet.add(8);
    numSet.add(10);
    numSet.add(16);

    System.out.println("** Ceiling method Example **");
    //Returns the least element in this set greater than or equal to the 
    //given element
    int num = numSet.ceiling(9);
    System.out.println("num- " + num);

    System.out.println("** Floor method Example **");
    //Returns the greatest element in this set less than or equal to the 
    //given element
    num = numSet.floor(9);
    System.out.println("num- " + num);

    System.out.println("** Lower method Example **");
    //Returns the greatest element in this set strictly less than the given element
    num = numSet.lower(10);
    System.out.println("num- " + num);
  }
}
Output
** Ceiling method Example **
num- 10
** Floor method Example **
num- 8
** Lower method Example **
num- 8

That's all for the topic Java ConcurrentSkipListSet With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

Java ConcurrentSkipListMap With Examples

This post talks about the ConcurrentSkipListMap class from the java.util.concurrent package and the interface ConcurrentNavigableMap this class implements.

ConcurrentSkipListMap in Java

ConcurrentSkipListMap is a thread-safe, scalable Map that stores its elements in sorted manner. By default map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.

Java ConcurrentSkipListMap class implements a concurrent variant of SkipLists providing expected average log(n) time cost for the containsKey, get, put and remove operations and their variants. Insertion, removal, update, and access operations safely execute concurrently by multiple threads. ConcurrentSkipListMap was added in Java 1.6.

SkipList data structure

As per https://en.wikipedia.org/wiki/Skip_list - Skip list is a data structure that allows fast search within an ordered sequence of elements. Fast search is made possible by maintaining a linked hierarchy of subsequences, with each successive subsequence skipping over fewer elements than the previous one.

As you can see for faster search skip list requires elements to be in an ordered sequence, that is why elements are sorted in the Java ConcurrentSkipListMap.

ConcurrentNavigableMap in Java

ConcurrentSkipListMap in Java implements the ConcurrentNavigableMap interface where ConcurrentNavigableMap extends ConcurrentMap and NavigableMap interfaces in turn.

  • ConcurrentMap- A Map providing thread safety and atomicity guarantees. So there are methods like putIfAbsent(), remove() where the action is performed atomically.
  • NavigableMap- A SortedMap extended with navigation methods returning the closest matches for given search targets. So it has methods like lowerEntry(K), floorEntry(K), lowerKey(K), floorKey(K), ceilingKey(K) for returning closest match to the passed key.

ConcurrentNavigableMap interface was added in Java 1.6.

Java ConcurrentSkipListMap constructors

  • ConcurrentSkipListMap()- Constructs a new, empty map, sorted according to the natural ordering of the keys.
  • ConcurrentSkipListMap(Comparator<? super K> comparator)- Constructs a new, empty map, sorted according to the specified comparator.
  • ConcurrentSkipListMap(Map<? extends K,? extends V> m)- Constructs a new map containing the same mappings as the given map, sorted according to the natural ordering of the keys.
  • ConcurrentSkipListMap(SortedMap<K,? extends V> m)- Constructs a new map containing the same mappings and using the same ordering as the specified sorted map.

ConcurrentSkipListMap Java example

public class SkipMapDemo {
  public static void main(String[] args) {
    // Creating ConcurrentSkipListMap
    ConcurrentNavigableMap<String, String> cityTemperatureMap = new ConcurrentSkipListMap<String, String>();

    // Storing elements
    cityTemperatureMap.put("Delhi", "24");
    cityTemperatureMap.put("Mumbai", "32");
    cityTemperatureMap.put("Chennai", "35");
    cityTemperatureMap.put("Bangalore", "22" );
    cityTemperatureMap.put("Kolkata", "28");

    Set<Map.Entry<String, String>> cityTempSet = cityTemperatureMap.entrySet();
    cityTempSet.forEach((m)->System.out.println("key " + m.getKey() 
				 + " value " + m.getValue()));
  }
}
Output
key Bangalore value 22
key Chennai value 35
key Delhi value 24
key Kolkata value 28
key Mumbai value 32

As you can see the elements are sorted by their keys and natural ordering is used as no Comparator is passed while creating the ConcurrentSkipListMap.

ConcurrentSkipListMap doesn't allow null

ConcurrentSkipListMap class in Java does not permit the use of null keys or values. Adding a null key or value results in NullPointerException being thrown.

For example- In the example code used above if you try to add null key result would be as follows.

cityTemperatureMap.put(null, "28");

Exception in thread "main" java.lang.NullPointerException
	at java.base/java.util.concurrent.ConcurrentSkipListMap.doPut(ConcurrentSkipListMap.java:597)
	at java.base/java.util.concurrent.ConcurrentSkipListMap.put(ConcurrentSkipListMap.java:1345)

Navigational methods in ConcurrentSkipListMap example

public class SkipMapDemo {

  public static void main(String[] args) {
    // Creating ConcurrentSkipListMap
    ConcurrentNavigableMap<Integer, String> numberMap = new ConcurrentSkipListMap<Integer, String>();

    // Storing elements
    numberMap.put(1, "ONE");
    numberMap.put(2, "TWO");
    numberMap.put(5, "FIVE");
    numberMap.put(8, "EIGHT" );
    numberMap.put(10, "TEN");
    numberMap.put(16, "SIXTEEN");

    System.out.println("** reverse order view of the map **");

    //Returns a reverse order view of the mappings
    ConcurrentNavigableMap<Integer, String> reverseNumberMap = numberMap.descendingMap();

    Set<Map.Entry<Integer, String>> numSet = reverseNumberMap.entrySet();
    numSet.forEach((m)->System.out.println("key " + m.getKey() 
         + " value " + m.getValue()));
    System.out.println("** First entry in the the map **");
    //Returns a key-value mapping associated with the least key in this map
    Map.Entry<Integer, String> mapEntry = numberMap.firstEntry();
    System.out.println("key " + mapEntry.getKey() + " value " + mapEntry.getValue());

    System.out.println("** Floor entry Example **");
    //Returns a key-value mapping associated with the greatest key less than or equal to the given key
    mapEntry = numberMap.floorEntry(7);
    System.out.println("key " + mapEntry.getKey()  + " value " + mapEntry.getValue());

    System.out.println("** Ceiling entry Example **");
    //Returns a key-value mapping associated with the least key greater than or equal to the given key
    mapEntry = numberMap.ceilingEntry(7);
    System.out.println("key " + mapEntry.getKey()  + " value " + mapEntry.getValue());
  }
}
Output
** reverse order view of the map **
key 16 value SIXTEEN
key 10 value TEN
key 8 value EIGHT
key 5 value FIVE
key 2 value TWO
key 1 value ONE
** First entry in the the map **
key 1 value ONE
** Floor entry Example **
key 5 value FIVE
** Ceiling entry Example **
key 8 value EIGHT

That's all for the topic Java ConcurrentSkipListMap With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

Java Reflection – Class Fields

Using Java Reflection you can get information about the class fields and get and set field values at run time. In Java Reflection API there is a class java.lang.reflect.Field that has methods for accessing field's type, field’s modifier and setting and getting values of a field.

Getting Field instance

First thing is to get the instance of Field class for that you will have to use methods of the java.lang.Class as that class is the entry point for all reflection operations.

There are 4 methods for getting field instance-

  1. getField(String name)- Returns a Field object representing the public member field of the class or interface.
  2. getFields()- Returns an array containing Field objects reflecting all the accessible public fields of the class or interface.
  3. getDeclaredField(String name)- Returns a Field object that reflects the specified declared field (even private) of the class or interface represented by this Class object.
  4. getDeclaredFields()- Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields.

Getting information about class fields – Java example

This example shows how to get information like type, modifier of individual/all fields of a class. Methods of the Field class used are-

  • getType() method of the Field class returns the declared type for the field.
  • getModifiers() method of the field class returns the modifiers for the field as an integer.
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Set;

public class FieldReflectionDemo {
  public String str = "Reflection";
  private int i;
  public boolean flag = false;
  public Set<String> citySet;
    
  public static void main(String[] args) {
    try {
      FieldReflectionDemo obj = new FieldReflectionDemo();
      Class<?> c = obj.getClass();
      // get specific field
      Field f = c.getField("str");
      // getting field type
      Class<?> type = f.getType();
      // getting field modifiers
      int mod = f.getModifiers();
      System.out.println("Field name - " + f.getName()); 
      System.out.println("Field type - " + type.getName());
      System.out.println("Field modifiers - " + Modifier.toString(mod));
      System.out.println("--- Getting all fields ---");
      Field[] fields = c.getDeclaredFields();
      for(Field field : fields) {
        System.out.println("Field name - " + field.getName()); 
        System.out.println("Field type - " + field.getType());
        System.out.println("Field modifiers - " + Modifier.toString(field.getModifiers()));
      }        
    } catch (NoSuchFieldException | SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
Field name - str
Field type - java.lang.String
Field modifiers - public
--- Getting all fields ---
Field name - str
Field type - class java.lang.String
Field modifiers - public
Field name - i
Field type - int
Field modifiers - private
Field name - flag
Field type - boolean
Field modifiers - public
Field name - citySet
Field type - interface java.util.Set
Field modifiers - public

Getting and setting values

For getting value there is get(Object obj) method which returns the value of the field represented by this Field, on the specified object.

For Setting value there is set(Object obj, Object value) method which sets the field represented by this Field object on the specified object argument to the specified new value.

import java.lang.reflect.Field;
import java.util.Set;

public class FieldReflectionDemo {
  public String str = "Reflection";
  private int i;
  public boolean flag = false;
  public Set<String> citySet;
    
  public static void main(String[] args) {
    try {
      FieldReflectionDemo obj = new FieldReflectionDemo();
      Class<?> c = obj.getClass();
      // get specific field
      Field f = c.getField("str");
      // show value - get method
      System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));
      // set new value
      f.set(obj, "New Value");
      System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));        
    } catch (IllegalAccessException | NoSuchFieldException | SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
Field name- str Value- Reflection
Field name- str Value- New Value

Getting and setting value of a private field

You can even set value of a private field using Reflection. For that you need to set the accessible as true using setAccesssible() method.

In the example we have a class Access with one private int field i. In FieldReflectionDemo class we’ll access this field using reflection and set a value to it. If you don’t set the accessible flag using setAccesssible() method it will throw IllegalAccessException as shown below.

class Access{
  private int i;
}

public class FieldReflectionDemo {
  public String str = "Reflection";
  public boolean flag = false;
  public Set<String> citySet;
    
  public static void main(String[] args) {
    try {
      Access obj = new Access();
      Class<?> c = obj.getClass();
      // get specific field
      Field f = c.getDeclaredField("i");
      // show value - get method
      System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));
      // set new value
      f.set(obj, 7);
      System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));       
    } catch (IllegalAccessException | NoSuchFieldException | SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
java.lang.IllegalAccessException: class com.knpcode.programs.FieldReflectionDemo cannot access a member of class com.knpcode.programs.Access with modifiers "private"

Run again after making this change and you will be able to access even the private fields.

Field f = c.getDeclaredField("i");
f.setAccessible(true);
Output
Field name- i Value- 0
Field name- i Value- 7

Reference: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/reflect/Field.html

That's all for the topic Java Reflection – Class Fields. If something is missing or you have something to share about the topic please write a comment.


You may also like