# Java `CopyOnWriteArrayList`类

> 原文： [https://howtodoinjava.com/java/collections/java-copyonwritearraylist/](https://howtodoinjava.com/java/collections/java-copyonwritearraylist/)

Java `CopyOnWriteArrayList`是`ArrayList`的[线程安全](https://howtodoinjava.com/java/multi-threading/what-is-thread-safety/)变体，其中的所有可变操作（添加，设置等）均通过对基础[数组](https://howtodoinjava.com/java-array/)进行全新复制来实现。

它的[**不可变**](https://howtodoinjava.com/java/basics/how-to-make-a-java-class-immutable/)快照式迭代器方法在创建[迭代器](https://howtodoinjava.com/java/collections/java-iterator/)时使用了对数组状态的引用。 这在遍历操作远远超过列表更新操作且我们不想同步遍历并且在更新列表时仍希望线程安全的用例中很有用。

```java
Table of Contents

1\. CopyOnWriteArrayList Hierarchy
2\. CopyOnWriteArrayList Features
3\. CopyOnWriteArrayList Example
4\. CopyOnWriteArrayList Constructors
5\. CopyOnWriteArrayList Methods
6\. CopyOnWriteArrayList Usecases
7\. CopyOnWriteArrayList Performance
8\. Conclusion
```

## 1\. `CopyOnWriteArrayList`层次结构

`CopyOnWriteArrayList`类实现以下接口 – `List`，`RandomAccess`，[`Cloneable`](https://howtodoinjava.com/java/cloning/a-guide-to-object-cloning-in-java/)和[`serializable`](https://howtodoinjava.com/java/serialization/custom-serialization-readobject-writeobject/)。

```java
public class CopyOnWriteArrayList<E>
    implements 	List<E>, 
    			RandomAccess, 
    			Cloneable, 
    			Serializable 

{
	private transient volatile Object[] array;

	//implementation
}

```

## 2\. `CopyOnWriteArrayList`特性

有关 Java `CopyOnWriteArrayList`类的重要知识是：

*   `CopyOnWriteArrayList`类实现`List`和`RandomAccess`接口，因此提供`ArrayList`类中可用的所有特性。
*   使用`CopyOnWriteArrayList`进行更新操作的成本很高，因为每个突变都会创建基础数组的克隆副本，并为其添加/更新元素。
*   它是`ArrayList`的线程安全版本。 每个访问列表的线程在初始化此列表的迭代器时都会看到自己创建的后备数组快照版本。
*   因为它在创建迭代器时获取基础数组的快照，所以它不会抛出`ConcurrentModificationException`。
*   不支持对迭代器的删除操作（删除，设置和添加）。 这些方法抛出`UnsupportedOperationException`。
*   `CopyOnWriteArrayList`是**同步列表**的并发替代，当迭代次数超过突变次数时，它提供了更好的并发性。
*   它允许重复的元素和异构对象（使用泛型来获取编译时错误）。
*   因为它每次创建迭代器时都会创建一个数组的新副本，所以**性能比`ArrayList`慢**。

## 3\. `CopyOnWriteArrayList`示例

显示在不同时间创建的迭代器如何查看`CopyOnWriteArrayList`中`list`的快照版本的 Java 程序。 在给定的示例中，当列表具有元素（`1,2,3`）时，我们首先创建了`list`和`itr1`。

然后，我们在列表中添加了另一个元素，并再次创建了一个迭代器`itr2`。

最后，我们验证了两个迭代器中的元素。

```java
CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>(new Integer[] {1,2,3});

System.out.println(list);	//[1, 2, 3]

//Get iterator 1
Iterator<Integer> itr1 = list.iterator();

//Add one element and verify list is updated
list.add(4);

System.out.println(list);	//[1, 2, 3, 4]

//Get iterator 2
Iterator<Integer> itr2 = list.iterator();

System.out.println("====Verify Iterator 1 content====");

itr1.forEachRemaining(System.out :: println);	//1,2,3

System.out.println("====Verify Iterator 2 content====");

itr2.forEachRemaining(System.out :: println);	//1,2,3,4

```

程序输出。

```java
[1, 2, 3]
[1, 2, 3, 4]
====Verify Iterator 1 content====
1
2
3
====Verify Iterator 2 content====
1
2
3
4

```

## 4\. `CopyOnWriteArrayList`构造器

*   **`CopyOnWriteArrayList()`**：创建一个空列表。
*   **`CopyOnWriteArrayList(Collection c)`**：创建一个列表，其中包含指定集合的​​元素，并按集合的迭代器返回的顺序排列。
*   **`CopyOnWriteArrayList(object[] array)`**：创建一个保存给定数组副本的列表。

## 5\. `CopyOnWriteArrayList`方法

`CopyOnWriteArrayList`类支持`ArrayList`类支持的所有方法。 该行为仅在迭代器（**快照迭代器**）和列表中发生突变时创建的新支持数组的情况下有所不同。

此外，它提供了一些此类之外的方法。

*   **`boolean addIfAbsent(Object o)`**：如果不存在，则追加元素。
*   **`int addAllAbsent(Collection c)`**：按指定集合的​​迭代器返回的顺序，将指定集合中尚未包含在此列表中的所有元素追加到此列表的末尾 。

对于所有受支持的其他方法，请访问[`ArrayList`](https://howtodoinjava.com/java-arraylist/)方法部分。

## 6\. Java `CopyOnWriteArrayList`用例

在以下情况下，我们更喜欢使用`CopyOnWriteArrayList`而不是常规`ArrayList`：

1.  当在并发环境中使用列表时。
2.  迭代次数超过了变异操作的次数。
3.  迭代器在创建时必须具有列表的快照版本。
4.  我们不想[以编程方式同步线程访问](https://howtodoinjava.com/java/multi-threading/wait-notify-and-notifyall-methods/)。

## 7\. Java `CopyOnWriteArrayList`性能

由于每次更新列表时都要增加创建新支持数组的步骤，因此其性能比`ArrayList`差。
读取操作没有性能开销，并且两个类执行相同的操作。

## 8\. 总结

在此 Java 集合教程中，我们学习了使用`CopyOnWriteArrayList`类，它的[构造器](https://howtodoinjava.com/oops/java-constructors/)，方法和用例。 我们学习了`CopyOnWriteArrayList`内部在 Java 中的工作原理以及`CopyOnWriteArrayList`与同步`ArrayList`的工作原理。

我们通过 Java `CopyOnWriteArrayList`示例程序演示了快照迭代器的工作方式。

在评论中把您的问题交给我。

学习愉快！

参考：

[`CopyOnWriteArrayList` Java 文档](https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/CopyOnWriteArrayList.html)