CopyOnWriteArraySet in Java
Last Updated :
12 Feb, 2025
In Java, the CopyOnWriteArraySet is the part of the java.util.concurrent package and is used to handle thread-safe operations in multi-threaded environments. It is ideal when the set is frequently read but infrequently modified. The set ensures safe access for multiple threads, as it creates a new copy of the set each time a modification is made, making reads efficient and safe. However, this comes at the cost of slower performance for modifications.
- CopyOnWriteArraySet uses a CopyOnWriteArrayList internally.
- Multiple threads can perform updates simultaneously, but only one thread can iterate the set at a time without encountering ConcurrentModificationException.
- Iterators can only perform read operations. Any attempt to modify the set during iteration throws an UnsupportedOperationException
- CopyOnWriteArraySet is Ideal for small sets where read operations are much more frequent than modifications, and where minimizing synchronization overhead is crucial.
CopyOnWriteArraySet is a class that implements the Set interface. The Set interface extends the Collection interface. The Collection interface extends the Iterable interface and the Object is the root of this hierarchy.
Example 1: This example demonstrates how CopyOnWriteArraySet allows safe concurrent reading and writing by multiple threads without throwing ConcurrentModificationException.
Java
// Java Program to demonstrates the
// working of CopyOnWriteArraySet
import java.util.concurrent.CopyOnWriteArraySet;
public class Geeks {
public static void main(String[] args)
{
// Create a CopyOnWriteArraySet
CopyOnWriteArraySet<String> s
= new CopyOnWriteArraySet<>();
// Adding elements to the set
s.add("Geek1");
s.add("Geek2");
s.add("Geek3");
System.out.println("Set: " + s);
// Creating a thread that reads from the set
Thread readerThread = new Thread(() -> {
for (String item : s) {
System.out.println("Reading: " + item);
}
});
// Creating a thread that modifies the set
Thread writerThread = new Thread(() -> {
s.add("Grapes");
System.out.println("Added Geeks");
});
// Start both threads
readerThread.start();
writerThread.start();
}
}
OutputSet: [Geek1, Geek2, Geek3]
Added Geeks
Reading: Geek1
Reading: Geek2
Reading: Geek3
Hierarchy of CopyOnWriteArraySet
Declarartion of CopyOnWriteArraySet
In Java, the declaration of CopyOnWriteArraySet can be done as:
CopyOnWriteArraySet<Type> setName = new CopyOnWriteArraySet<>();
- Parameter: Specifies the type of elements the set will hold. It could be any class or interface, such as String or Integer.
- Return Type: Returns a thread-safe CopyOnWriteArraySet of the specified type.
Constructors
Constructors | Description |
|---|
CopyOnWriteArraySet() | Creates an empty set. |
CopyOnWriteArraySet(Collection c) | Creates a set containing all of the elements of the specified collection. |
Example 2: This example demonstrates how CopyOnWriteArraySet allows thread-safe modification and iteration, where elements can be added by a child thread and safely iterated without causing concurrency issues or exception.
Java
// Java Program to demonstrates the working of
// CopyOnWriteArraySet Class
import java.util.*;
import java.util.concurrent.*;
class Geeks extends Thread {
static CopyOnWriteArraySet<String> s
= new CopyOnWriteArraySet<>();
public void run()
{
// Child thread trying to add
// new element in the Set object
s.add("D");
}
public static void main(String[] args)
{
// Adding elements using add() method
s.add("A");
s.add("B");
s.add("C");
// We create a child thread that
// is going to modify CopyOnWriteArraySet s
Geeks t = new Geeks();
// Running the child thread
// using start() method
t.start();
// Try block to check for exceptions
try {
// Waiting for the thread to add the element
// Join ensures that main thread waits for the
// child thread to finish
t.join();
}
// Catch block to handle exceptions
catch (InterruptedException e) {
System.out.println("Child thread interrupted.");
}
System.out.println(
"Set after child thread modification: " + s);
// Now we iterate through the CopyOnWriteArraySet
// and we won't get any exception.
Iterator<String> itr = s.iterator();
while (itr.hasNext()) {
String str = itr.next();
System.out.println(s);
if (str.equals("C")) {
// You cannot remove an element directly
// using the iterator's remove() So instead
// we can use remove() method of
// CopyOnWriteArraySet
// Removing element C
s.remove(str);
}
}
System.out.println("Final Set: " + s);
}
}
OutputSet after child thread modification: [A, B, C, D]
[A, B, C, D]
[A, B, C, D]
[A, B, C, D]
[A, B, D]
Final Set: [A, B, D]
Example 3: This example demonstrates how to iterate over a CopyOnWriteArraySet, showing that it allows re-iteration without causing concurrency issues, even after elements are added.
Java
// Iterate over a CopyOnWriteArraySet
import java.util.*;
import java.util.concurrent.*;
class Geeks {
public static void main(String[] args)
{
// Creating an instance of CopyOnWriteArraySet
CopyOnWriteArraySet<String> s
= new CopyOnWriteArraySet<>();
// Adding elements using add() method
s.add("GeeksforGeeks");
// Creating an iterator after adding the elements
Iterator<String> i = s.iterator();
// Display message
System.out.println("Set contains:");
// Printing the contents of the set to the console
while (i.hasNext()) {
System.out.println(i.next());
}
// Re-initialize the iterator
// to start iteration again
i = s.iterator();
System.out.println(
"Set contains after re-iteration:");
// Printing the elements to the console
while (i.hasNext()) {
System.out.println(i.next());
}
}
}
OutputSet contains:
GeeksforGeeks
Set contains after re-iteration:
GeeksforGeeks
Methods
Method | Description |
|---|
| add(E e) | Adds the specified element to this set if it is not already present. |
| addAll(Collection<? extends E> c) | Adds all of the elements in the specified collection to this set if they’re not already present. |
| clear() | Removes all of the elements from this set. |
| contains(Object o) | Returns true if this set contains the specified element. |
| containsAll(Collection<?> c) | Returns true if this set contains all of the elements of the specified collection. |
| equals(Object o) | Compares the specified object with this set for equality. |
| 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. |
| isEmpty() | Returns true if this set contains no elements. |
| iterator() | Returns an iterator over the elements contained in this set in the order in which these elements were added. |
| remove(Object o) | Removes the specified element from this set if it is present. |
| removeAll(Collection<?> c) | Removes from this set all of its elements that are contained in the specified collection. |
| removeIf(Predicate<? super E> filter) | Removes all of the elements of this collection that satisfy the given predicate. |
| retainAll(Collection<?> c) | Retains only the elements in this set that are contained in the specified collection. |
| size() | Returns the number of elements in this set. |
| spliterator() | Returns a Spliterator over the elements in this set in the order in which these elements were added. |
| toArray() | Returns an array containing all of the elements in this set. |
| 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. |
- Method inherited from class java.util.AbstractSet:
- hashCode(): Returns the hash code value for this set.
- Methods inherited from class java.util.AbstractCollection:
- toString(): Returns a string representation of this collection
- Methods inherited from interface java.util.Collection:
- parallelStream(): Returns a possibly parallel Stream with this collection as its source.
- stream(): Returns a sequential Stream with this collection as its source.
HashSet vs CopyOnWriteArraySet
Property | HashSet | CopyOnWriteArraySet |
|---|
Package | It belongs to java.util package | It belongs to java.util.concurrent package |
|---|
Synchronization | HashSet is not synchronized, meaning it’s not thread-safe. | CopyOnWriteArraySet is synchronized and thread-safe. |
|---|
Iterators | Iterators returned my methods iterator() and listiterator() are fail-fast. | Iterators returned are fail-safe |
|---|
Added In Version | It was added in JDK 1.2 | It was added in JDK 1.5 |
|---|
Performance | It is fast because it does not required synchronzation | It is slower because every modification creates a new copy of the underlying array. |
|---|
Exception | It may throw ConcurrentModificationException. If multiple threads modify it while iterating. | It does not throw ConcurrentModificationException because modifications are done on a copy of the internal array. |
|---|
Explore
Java Basics
OOP & Interfaces
Collections
Exception Handling
Java Advanced
Practice Java