Java中的CopyOnWriteArraySet
CopyOnWriteArraySet 是Java集合框架的成员之一。它是一个使用内部CopyOnWriteArrayList进行所有操作的Set。它在JDK 1.5中引入,可以说它是Set的线程安全版本。要使用此类,我们需要从java.util.concurrent包中导入它。

它共享Set的一些属性,并具有其自己的属性,如下所列:
- CopyOnWriteArraySet的内部实现仅是CopyOnWriteArrayList。
- 多个线程能够同时执行更新操作,但对于每个更新操作,都会创建一个单独的克隆副本。由于每次更新都会创建新的克隆副本,因此不建议使用CopyOnWriteArraySet进行多个更新操作。
- 当一个线程迭代Set时,其他线程可以执行更新操作,这里不会出现任何运行时异常,如ConcurrentModificationException。 。
- CopyOnWriteArraySet类的迭代器只能执行只读操作,不应执行删除操作,否则我们将得到运行时异常UnsupportedOperationException。 。
- 在应用程序中使用CopyOnWriteArraySet,其中集合大小通常保持较小,只读操作远远超过变异操作,并且在遍历期间需要防止线程干扰。
- CopyOnWriteArraySet有助于最小化程序员控制的同步步骤,并将控制移动到内置的,经过充分测试的API中。
类层次结构如下:
java.lang.Object
↳ java.util.AbstractCollection<E>
↳ java.util.AbstractSet<E>
↳ java.util.concurrent.CopyOnWriteArraySet<E>
语法: 声明
public class CopyOnWriteArraySet<E> extends AbstractSet<E> implements Serializable
在这里, E 是存储在此集合中的元素类型。它实现了 Serializable , **Iterable
CopyOnWriteArraySet的构造函数
1. CopyOnWriteArraySet() :创建一个空集。
CopyOnWriteArraySet<E> c = new CopyOnWriteArraySet<E>();
2. CopyOnWriteArraySet(Collection c) :创建包含指定集合中所有元素的集合。
CopyOnWriteArraySet<E> c = new CopyOnWriteArraySet<E>(Collection c);
例子:
// Java程序,演示CopyOnWriteArraySet类
// 导入所需类
import java.util.*;
import java.util.concurrent.*;
// 主类
class ConcurrentDemo extends Thread {
static CopyOnWriteArraySet l
= new CopyOnWriteArraySet();
// 方法
public void run()
{
// 子线程尝试在Set对象中添加新元素
l.add("D");
}
// 方法2
// 主驱动方法
public static void main(String[] args)
{
// 使用add()方法添加元素
l.add("A");
l.add("B");
l.add("C");
// 我们创建一个子线程,修改CopyOnWriteArraySet l
ConcurrentDemo t = new ConcurrentDemo();
// 运行子线程
t.start();
// 等待线程添加元素
// 尝试块检查异常
try {
Thread.sleep(2000);
}
// 捕获块以处理异常
catch (InterruptedException e) {
// 打印语句
System.out.println(
"child going to add element");
}
System.out.println(l);
// 现在,我们通过CopyOnWriteArraySet迭代,并且我们不会得到异常
Iterator itr = l.iterator();
while (itr.hasNext()) {
String s = (String)itr.next();
System.out.println(s);
if (s.equals("C")) {
// 在此处,会抛出运行时异常
itr.remove();
}
}
}
}
输出:

迭代CopyOnWriteArraySet
我们可以使用iterator()方法按照添加元素的顺序迭代此集合中包含的元素。返回的迭代器提供了构建迭代器时集合状态的不可变快照。由于这个属性, GeeksforGeeks 在第一次迭代时不会被输出。在迭代时不需要同步。迭代器不支持remove方法。
例子:
// Java程序,演示使用
// CopyOnWriteArraySet类进行迭代
// 导入所需的类
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
// 主类
// IteratingCopyOnWriteArraySet
class GFG {
// 主函数
public static void main(String[] args)
{
// 创建CopyOnWriteArraySet的实例
CopyOnWriteArraySet<String> set
= new CopyOnWriteArraySet<>();
// 初始化一个迭代器
Iterator itr = set.iterator();
// 使用add()方法添加元素
set.add("GeeksforGeeks");
// 仅显示消息
System.out.println("集合包含:");
// 将集合的内容打印到控制台
while (itr.hasNext())
System.out.println(itr.next());
// 添加了一个元素后的迭代器
itr = set.iterator();
// 仅显示消息
System.out.println("集合包含:");
// 将元素打印到控制台
while (itr.hasNext())
System.out.println(itr.next());
}
}
输出:
集合包含:
集合包含:
GeeksforGeeks
CopyOnWriteArraySet中的方法
| 方法 | 行为 |
|---|---|
| add(E e) | 如果该集合中还没有该元素,则将指定元素添加到此集合中。 |
| addAll(Collection extends E> c) | 将指定集合中的所有元素添加到此集合中,如果它们尚未存在于此集合中。 clear() | 从此集合中删除所有元素。 contains(Object o) | 如果此集合包含指定的元素,则返回true。 containsAll(Collection> c) |
如果此集合包含指定的集合中的所有元素,则返回true。 |
| equals(Object o) | 将指定对象与此集合进行比较以检查它们是否相等。 |
| forEach(Consumer super E> action) | 对Iterable的每个元素执行给定操作,直到所有元素都已处理完成或操作引发异常。 isEmpty() | 如果此集合不包含任何元素,则返回true。 iterator() | 按照添加这些元素的顺序,返回一个迭代器,该迭代器遍历此集合中包含的元素。 remove(Object o) | 如果存在,则从此集合中删除指定元素。 removeAll(Collection> c) |
从此集合中删除与指定集合中包含的元素相同的所有元素。 |
| removeIf(Predicate super E> filter) | 删除此集合的所有满足给定谓词的元素。 retainAll(Collection> c) |
仅保留此集合中包含在指定集合中的元素。 |
| size() | 返回此集合中的元素数。 |
| spliterator() | 按照添加这些元素的顺序,返回一个Spliterator,该Spliterator遍历此集合中包含的元素。 |
| toArray() | 返回包含此集合中所有元素的数组。 |
| toArray(T[] a) | 返回一个包含此集合中所有元素的数组,返回数组的运行时类型与指定数组的类型相同。 |
继承自java.util.AbstractSet类的方法
| 方法 | 描述 |
|---|---|
| hashCode() | 返回此集合的哈希码值。 |
继承自java.util.AbstractCollection类的方法
| 方法 | 描述 |
|---|---|
| toString() | 返回此集合的字符串表示形式。 |
继承自java.util.Collection接口的方法
| 方法 | 描述 |
|---|---|
| parallelStream() | 以此集合为源返回可能出现的并行Stream。 |
| stream() | 以此集合为源返回顺序Stream。 |
HashSet vs CopyOnWriteArraySet
| PROPERTY | HashSet | CopyOnWriteArraySet |
|---|---|---|
| 包 | 属于 java.util 包。 | 属于 java.util.concurrent 包。 |
| 同步 | 同步意味着只有一个线程可以访问或修改它。HashSet不同步。 | 它是同步的。 |
| 迭代器 | 由方法 iterator() 和 listiterator() 返回的迭代器是 fail-fast 。 | 返回的迭代器是 fail-safe 。 |
| 在版本中添加 | 它在JDK 1.2中添加。 | 它在JDK 1.5中添加。 |
| 性能 | 它很快,因为它不同步。 | 它比HashSet慢,因为它是同步的。 |
| 异常 | 它可能会抛出ConcurrentModificationException,因为许多线程可以同时访问它。 | 它不会抛出ConcurrentModificationException,因为它是同步的。 |
极客教程