Java 5 added several concurrent collection classes as a thread safe alternative to their normal collection counterparts which are not thread safe. For example, ConcurrentHashMap as a thread safe alternative to HashMap, CopyOnWriteArrayList as a thread safe alternative to ArrayList. In the same way, CopyOnWriteArraySet in Java is added as a thread safe alternative to HashSet in Java.
CopyOnWriteArraySet class in Java
CopyOnWriteArraySet is a part of the java.util.concurrent package. It extends AbstractSet and implements the Set interface, ensuring that only unique elements can be stored. Internally, it is backed by a CopyOnWriteArrayList, which means all operations are delegated to this underlying list.
CopyOnWriteArraySet is thread-safe
As already mentioned CopyOnWriteArraySet in Java is thread-safe. The thread‑safety of CopyOnWriteArraySet comes from its underlying mechanism.
- Since it uses CopyOnWriteArrayList internally so thread-safety is achieved in the same way in CopyOnwriteArraySet as in CopyOnWriteArrayList; all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.
- This ensures that read operations can safely occur without locking, as readers always see a consistent snapshot of the data.
- As a result, multiple threads can traverse the set without interference, making it ideal for concurrent read‑heavy scenarios.
When to Use CopyOnWriteArraySet?
Because each write operation involves copying the entire array to create a fresh copy, CopyOnWriteArraySet is best suited for situations where:
- The set size is relatively small.
- Read-only operations vastly outnumber mutative operations
- You need to avoid concurrency issues among threads during iteration.
As example when you have a unique set of values, which are read more by threads and operations like add or set are very rarely used, CopyOnWriteArraySet would be a good choice.
Java CopyOnWriteArraySet constructors
CopyOnWriteArraySet class has two constructors.
- CopyOnWriteArraySet()- Creates an empty set.
- CopyOnWriteArraySet(Collection<? extends E> c)- Creates a set containing all of the elements of the specified collection.
CopyOnWriteArraySet Java example
Here is a simple Java example showing the creation of CopyOnWriteArraySet and adding elements to it. This set is later iterated using for-each loop to display the set elements.
public class CWSetDemo {
public static void main(String[] args) {
Set<String> citySet = new CopyOnWriteArraySet<>();
citySet.add("NYC");
citySet.add("London");
citySet.add("Prague");
citySet.add("Berlin");
citySet.add("London");
// Iterating CopyOnWriteArraySet
for(String city : citySet) {
System.out.println("City name- " + city);
}
}
}
Output
City name- NYC City name- London City name- Prague City name- Berlin
In the code you can see that the London is added twice but it is not added again as Set doesn't allow duplicates. If CopyOnWriteArraySet already contains the element, the call leaves the set unchanged and returns false.
CopyOnWriteArraySet iterator
The iterator returned by CopyOnWriteArraySet is fail-safe which means any structural modification (Structural modifications are those that change the size of the collection or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results) made to the CopyOnwriteArraySet won't throw ConcurrentModificationException.
The iterator returned by concurrent collections like CopyOnWriteArrayList or CopyOnWriteArraySet uses the "snap-shot" style iterator in Java. The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException. The iterator will not reflect additions, removals, or changes to the list since the iterator was created. Note that in case of CopyOnWriteArraySet Iterators do not support the mutative remove operation. Any attempt to use iterator's remove() method will result in UnsupportedOperationException.
Iterate a CopyOnWriteArraySet Java example
In this Java program we'll try to iterate a CopyOnWriteArraySet and also create a thread which tries to add new element to the set simultaneously.
public class CWSDemo {
public static void main(String[] args) {
Set<Integer> numSet = new CopyOnWriteArraySet<Integer>();
// Adding 5 elements to the set
for(int i=1;i<=5;i++) {
numSet.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
numSet.add(6);
System.out.println("" + numSet);
}
}).start();
// get an iterator
Iterator<Integer> itr = numSet.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 thread adds a new element at the same time when the CopyOnWriteArraySet is iterated, still ConcurrentModificationException is not thrown. Since iterator get its own copy to iterate so the change is not reflected in that copy and the set still display elements 1-5 only.
If you uncomment the line itr.remove(); in the code it will throw UnsupportedOperationException when executed.
Output
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(Unknown Source) at org.netjs.prgrm.CWSDemo.main(CWSDemo.java:42) [1, 2, 3, 4, 5, 6]
Points to remember
- CopyOnWriteArraySet is thread-safe.
- CopyOnWriteArraySet internally uses CopyOnWriteArrayList for all of its operations.
- CopyOnWriteArraySet is best suited for applications in which set sizes generally stay small and read-only operations outnumber the mutative operations.
- For mutative operations (add, set, remove, etc.) copy of an underlying array is made thus making mutative operations expensive.
- Iterator returned by CopyOnWriteArraySet is fail-safe and cannot encounter interference from other threads because iteration happens on a separate copy.
That's all for this topic CopyOnWriteArraySet in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!
Related Topics
You may also like-