Java中的 CopyOnWriteArraySet
CopyOnWriteArraySet是Java集合框架的成员。它是一个使用内部 CopyOnWriteArrayList 进行所有操作的 Set。它是在 JDK 1.5 中引入的,可以说它是 Set 的线程安全版本。要使用这个类,我们需要从Java.util.concurrent 包中导入它。
它共享 Set 的一些属性,也有自己的属性,如下所示:
- CopyOnWriteArraySet 的内部实现仅为 CopyOnWriteArrayList。
- 多个线程能够同时执行更新操作,但对于每个更新操作,都会创建一个单独的克隆副本。至于每次更新都会创建一个新的克隆副本,这是昂贵的。因此,如果需要多次更新操作,则不建议使用 CopyOnWriteArraySet。
- 当一个线程迭代 Set 时,其他线程可以执行更新,这里我们不会得到像 ConcurrentModificationException 这样的运行时异常。
- CopyOnWriteArraySet 类的 Iterator 只能执行只读,不应该执行删除,否则会得到 Run-time exception UnsupportedOperationException 。
- 在集合大小通常保持较小、只读操作大大超过可变操作的应用程序中使用 CopyOnWriteArraySet,并且您需要在遍历期间防止线程之间的干扰。
- CopyOnWriteArraySet 有助于最大限度地减少程序员控制的同步步骤并将控制转移到内置的、经过良好测试的 API。
类层次结构如下:
java.lang.Object
↳ java.util.AbstractCollection
↳ java.util.AbstractSet
↳ java.util.concurrent.CopyOnWriteArraySet
语法:声明
public class CopyOnWriteArraySet extends AbstractSet implements Serializable
这里, E是存储在此 Collection 中的元素的类型。它实现了 Serializable 、 Iterable
CopyOnWriteArraySet 的构造函数
1. CopyOnWriteArraySet() :创建一个空集。
CopyOnWriteArraySet c = new CopyOnWriteArraySet();
2. CopyOnWriteArraySet(Collection c) :创建一个包含指定集合的所有元素的集合。
CopyOnWriteArraySet c = new CopyOnWriteArraySet(Collection c);
例子:
Java
// Java Program to Illustrate CopyOnWriteArraySet Class
// Importing required classes
import java.util.*;
import java.util.concurrent.*;
// Main class
class ConcurrentDemo extends Thread {
static CopyOnWriteArraySet l
= new CopyOnWriteArraySet();
// Method
public void run()
{
// Child thread trying to add
// new element in the Set object
l.add("D");
}
// Method 2
// Main driver method
public static void main(String[] args)
{
// Adding elements
// using add() method
l.add("A");
l.add("B");
l.add("C");
// We create a child thread
// that is going to modify
// CopyOnWriteArraySet l.
ConcurrentDemo t = new ConcurrentDemo();
// Running the child thread
// using start() method
t.start();
// Waiting for the thread to
// add the element
// Try block to check for exceptions
try {
Thread.sleep(2000);
}
// Catch block to handle exceptions
catch (InterruptedException e) {
// Print statement
System.out.println(
"child going to add element");
}
System.out.println(l);
// Now we iterate through the
// CopyOnWriteArraySet and we
// wont get exception.
Iterator itr = l.iterator();
while (itr.hasNext()) {
String s = (String)itr.next();
System.out.println(s);
if (s.equals("C")) {
// Here we will get
// RuntimeException
itr.remove();
}
}
}
}
Java
// Java program to Illustrate Iterating Over
// CopyOnWriteArraySet class
// Importing required classes
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
// Main class
// IteratingCopyOnWriteArraySet
class GFG {
// Main class
public static void main(String[] args)
{
// Creating an instance of CopyOnWriteArraySet
CopyOnWriteArraySet set
= new CopyOnWriteArraySet<>();
// Initial an iterator
Iterator itr = set.iterator();
// Adding elements
// using add() method
set.add("GeeksforGeeks");
// Display message only
System.out.println("Set contains: ");
// Printing the contents
// of set to the console
while (itr.hasNext())
System.out.println(itr.next());
// Iterator after adding an element
itr = set.iterator();
// Display message only
System.out.println("Set contains:");
// Printing the elements to the console
while (itr.hasNext())
System.out.println(itr.next());
}
}
输出:
遍历 CopyOnWriteArraySet
我们可以使用 iterator() 方法按照添加这些元素的顺序迭代该集合中包含的元素。返回的迭代器提供了构造迭代器时集合状态的不可变快照。由于此属性, GeeksforGeeks不会在第一次迭代时打印。迭代时不需要同步。迭代器不支持 remove 方法。
例子:
Java
// Java program to Illustrate Iterating Over
// CopyOnWriteArraySet class
// Importing required classes
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
// Main class
// IteratingCopyOnWriteArraySet
class GFG {
// Main class
public static void main(String[] args)
{
// Creating an instance of CopyOnWriteArraySet
CopyOnWriteArraySet set
= new CopyOnWriteArraySet<>();
// Initial an iterator
Iterator itr = set.iterator();
// Adding elements
// using add() method
set.add("GeeksforGeeks");
// Display message only
System.out.println("Set contains: ");
// Printing the contents
// of set to the console
while (itr.hasNext())
System.out.println(itr.next());
// Iterator after adding an element
itr = set.iterator();
// Display message only
System.out.println("Set contains:");
// Printing the elements to the console
while (itr.hasNext())
System.out.println(itr.next());
}
}
输出:
Set contains:
Set contains:
GeeksforGeeks
CopyOnWriteArraySet 中的方法
Method | Action Performed |
---|---|
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. |
从类Java.util.AbstractSet 继承的方法
METHOD | DESCRIPTION |
---|---|
hashCode() | Returns the hash code value for this set. |
从类Java.util.AbstractCollection 继承的方法
METHOD | DESCRIPTION |
---|---|
toString() | Returns a string representation of this collection. |
从接口Java.util.Collection 继承的方法
METHOD | DESCRIPTION |
---|---|
parallelStream() | Returns a possibly parallel Stream with this collection as its source. |
stream() | Returns a sequential Stream with this collection as its source. |
HashSet 与 CopyOnWriteArraySet
PROPERTY | HashSet | CopyOnWriteArraySet |
---|---|---|
Package | It belongs to java.util package | It belongs to java.util.concurrent package |
Synchronization | Synchronization means only one thread can access or modify it. HashSet is not synchronized. | It is synchronized. |
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 since it is not synchronized. | It is slower compared to HashSet since it is synchronized. |
Exception | It may throw ConcurrentModificationException since many threads can access it simultaneously. | It does not throws ConcurrentModificationException since it is synchronized. |