CopyOnWriteArraySet in Java
CopyOnWriteArraySet is a thread-safe Set implementation in Java that is based on CopyOnWriteArrayList.
It is part of the java.util.concurrent package and is useful in multi-threaded scenarios where reads are more frequent than writes.
What is CopyOnWriteArraySet?
- A Set that does not allow duplicates
- Internally backed by CopyOnWriteArrayList
- Thread-safe without using explicit synchronization
- Iterators are fail-safe (do not throw
ConcurrentModificationException) - Ideal for read-heavy collections
Package
import java.util.concurrent.CopyOnWriteArraySet;
Features of CopyOnWriteArraySet
| Feature | Description |
|---|---|
| Thread-safe | Supports concurrent access without external locks |
| No duplicates | Set semantics – duplicates are not allowed |
| Fail-safe iterator | Iterators work on a snapshot of the array |
| Backed by | CopyOnWriteArrayList |
| Performance | Writes are costly (copying array), reads are very fast |
| Null elements | Allows one null element |
Where CopyOnWriteArraySet Fits in Collection Hierarchy
Iterable
└── Collection
└── Set
└── CopyOnWriteArraySet
Implements:
Set<E>SerializableCloneable
How CopyOnWriteArraySet Works Internally
- Every mutative operation (
add,remove, etc.) creates a new copy of the internal array. - Iterators work on a snapshot of the array at the time of iterator creation → no
ConcurrentModificationException. - Reading operations (
contains,size, iteration) are fast and non-blocking.
Constructors
Default Constructor
CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
Constructor with Collection
List<String> list = Arrays.asList("A", "B", "C");
CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>(list);
Common Methods
| Method | Description |
|---|---|
add(E e) | Adds element if not present |
remove(Object o) | Removes element if present |
contains(Object o) | Checks if element exists |
size() | Returns number of elements |
isEmpty() | Checks if set is empty |
iterator() | Returns fail-safe iterator |
clear() | Removes all elements |
addAll(Collection c) | Adds all elements from another collection |
Example
import java.util.concurrent.CopyOnWriteArraySet;
public class Main {
public static void main(String[] args) {
CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
set.add("Apple");
set.add("Banana");
set.add("Cherry");
set.add("Apple"); // Duplicate ignored
System.out.println("Set: " + set);
set.remove("Banana");
System.out.println("After removal: " + set);
// Iteration
for (String s : set) {
System.out.println(s);
}
}
}
Output:
Set: [Apple, Banana, Cherry]
After removal: [Apple, Cherry]
Apple
Cherry
When to Use CopyOnWriteArraySet
- When reads are frequent and writes are rare
- For event listener lists
- For cache of read-mostly data
- When thread-safe iteration without locks is needed
Advantages
- Thread-safe without explicit locks
- Fail-safe iterators
- Fast read operations
- No duplicates allowed
Disadvantages
- Expensive write operations (array copy)
- Not suitable for write-heavy workloads
- Consumes more memory for large sets
Time Complexity
| Operation | Complexity |
|---|---|
add() | O(n) (due to array copy) |
remove() | O(n) |
contains() | O(n) |
size() | O(1) |
| Iteration | O(n) |
CopyOnWriteArraySet vs HashSet in Java
| Feature | CopyOnWriteArraySet | HashSet |
|---|---|---|
| Thread-safety | Thread-safe, internally synchronized (safe for concurrent access) | Not thread-safe; external synchronization needed for multi-threading |
| Underlying Structure | Backed by CopyOnWriteArrayList | Backed by a HashMap |
| Performance | Reads are very fast (no locks), writes are expensive (entire array copied on modification) | Fast for add, remove, and contains (hash-based) |
| Iteration | Iterators reflect a snapshot; no ConcurrentModificationException | Fail-fast iterators; throw ConcurrentModificationException if modified during iteration |
| Use-case | Ideal for mostly-read, rarely-written scenarios (event listeners, caching) | Ideal for general-purpose sets with frequent add/remove operations |
| Allows null | Yes, allows one null element | Yes, allows one null element |
| Duplicates | No duplicates allowed | No duplicates allowed |
| Memory | Higher memory usage for writes (copies array on every modification) | Memory-efficient for most scenarios |
Difference Between CopyOnWriteArraySet & CopyOnWriteArrayList
| Feature | CopyOnWriteArraySet | CopyOnWriteArrayList |
|---|---|---|
| Interface Implemented | Implements Set interface | Implements List interface |
| Duplicates Allowed | No duplicates allowed (Set property) | Duplicates allowed (List property) |
| Ordering | No guaranteed order (insertion order maintained due to underlying list) | Maintains insertion order |
| Thread-safety | Thread-safe; all mutative operations create a new copy | Thread-safe; all mutative operations create a new copy |
| Underlying Structure | Backed by CopyOnWriteArrayList internally | Backed by array |
| Iteration Behavior | Iterators reflect a snapshot, safe in concurrent access | Iterators reflect a snapshot, safe in concurrent access |
| Best Use-case | Mostly-read sets; where uniqueness is required | Mostly-read lists; duplicates and order matter |
| Performance | Writes are expensive (array copied on every add/remove) | Writes are expensive (array copied on every add/remove) |
| Allows null | Yes, allows one null | Yes, allows multiple nulls |
Points to Remember
CopyOnWriteArraySet = Thread-safe Set based on CopyOnWriteArrayList, ideal for read-heavy, low-write multi-threaded applications.
- Allows fail-safe iteration
- No duplicates
- Writes are costly, reads are fast
