📌  相关文章
📜  Java中的 CopyOnWriteArrayList

📅  最后修改于: 2022-05-13 01:55:45.161000             🧑  作者: Mango

Java中的 CopyOnWriteArrayList

CopyOnWriteArrayList 类是 JDK 1.5 中引入的,它实现了List 接口。它是ArrayList的增强版 其中所有修改(添加、设置、删除等)都是通过制作新副本来实现的。它位于Java.util.concurrent包中。它是为在并发环境中使用而创建的数据结构。

Java 中的 CopyOnWriteArrayList

以下是有关 CopyOnWriteArrayList 的几点:

  • 顾名思义,CopyOnWriteArrayList 创建底层 ArrayList 的克隆副本,对于某个点的每个更新操作,两者都会自动同步,由 JVM 负责。因此,对正在执行读操作的线程没有影响。
  • 使用成本很高,因为每次更新操作都会创建一个克隆副本。因此,如果我们的频繁操作是读操作,CopyOnWriteArrayList 是最好的选择。
  • 带下划线的数据结构是一个可增长的数组。
  • 它是 ArrayList 的线程安全版本。
  • 保留插入,允许重复、空和异构对象。
  • 关于 CopyOnWriteArrayList 的主要重点是 CopyOnWriteArrayList 的迭代器不能执行删除操作,否则我们会得到运行时异常UnsupportedOperationException。 CopyOnWriteArrayList 迭代器上的 add() 和 set() 方法也会抛出UnsupportedOperationException。 CopyOnWriteArrayList 的迭代器也永远不会抛出ConcurrentModificationException

宣言:

这里,E 是该集合中包含的元素的类型。

注意:该类实现了SerializableCloneableIterableCollection 、 ListRandomAccess接口。

构造函数:

1. CopyOnWriteArrayList() :创建一个空列表。

CopyOnWriteArrayList c = new CopyOnWriteArrayList();

2. CopyOnWriteArrayList(Collection obj) :创建一个包含指定集合元素的列表,按顺序,它们由集合的迭代器返回。

CopyOnWriteArrayList c = new CopyOnWriteArrayList(Collection obj);

3. CopyOnWriteArrayList(Object[] obj); :创建一个包含给定数组副本的列表。

CopyOnWriteArrayList c = new CopyOnWriteArrayList(Object[] obj);

例子:

Java
// Java program to illustrate
// CopyOnWriteArrayList class
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
 
public class ConcurrentDemo extends Thread {
 
    static CopyOnWriteArrayList l
        = new CopyOnWriteArrayList();
 
    public void run()
    {
        // Child thread trying to
        // add new element in the
        // Collection object
        l.add("D");
    }
 
    public static void main(String[] args)
        throws InterruptedException
    {
        l.add("A");
        l.add("B");
        l.add("c");
 
        // We create a child thread
        // that is going to modify
        // ArrayList l.
        ConcurrentDemo t = new ConcurrentDemo();
        t.run();
 
        Thread.sleep(1000);
 
        // Now we iterate through
        // the ArrayList and get
        // exception.
        Iterator itr = l.iterator();
        while (itr.hasNext()) {
            String s = (String)itr.next();
            System.out.println(s);
            Thread.sleep(1000);
        }
        System.out.println(l);
    }
}


Java
// Java program to illustrate
// CopyOnWriteArrayList class
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
 
class Demo {
    public static void main(String[] args)
    {
 
        CopyOnWriteArrayList list
            = new CopyOnWriteArrayList<>();
 
        // Initial Iterator
        Iterator itr = list.iterator();
        list.add("GfG");
        System.out.println("List contains: ");
        while (itr.hasNext())
            System.out.println(itr.next());
 
        // iterator after adding an element
        itr = list.iterator();
        System.out.println("List contains:");
        while (itr.hasNext())
            System.out.println(itr.next());
    }
}


输出
A
B
c
D
[A, B, c, D]

遍历CopyOnWriteArrayList:我们可以使用 iterator() 方法遍历 CopyOnWriteArrayList。需要注意的重要一点是,我们创建的迭代器是原始列表的不可变快照。由于这个属性,我们可以看到GfG在第一次迭代时没有打印出来。

Java

// Java program to illustrate
// CopyOnWriteArrayList class
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
 
class Demo {
    public static void main(String[] args)
    {
 
        CopyOnWriteArrayList list
            = new CopyOnWriteArrayList<>();
 
        // Initial Iterator
        Iterator itr = list.iterator();
        list.add("GfG");
        System.out.println("List contains: ");
        while (itr.hasNext())
            System.out.println(itr.next());
 
        // iterator after adding an element
        itr = list.iterator();
        System.out.println("List contains:");
        while (itr.hasNext())
            System.out.println(itr.next());
    }
}
输出
List contains: 
List contains:
GfG

CopyOnWriteArrayList 的方法:

METHOD

DESCRIPTION

add(E e)Appends the specified element to the end of this list.
add(int index, E element)Inserts the specified element at the specified position in this list.
addAll(Collection c)Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection’s iterator.
addAll(int index, Collection c)Inserts all of the elements in the specified collection into this list, starting at the specified position.
addAllAbsent(Collection c)Appends all of the elements in the specified collection that are not already contained in this list, to the end of this list, in the order that they are returned by the specified collection’s iterator.
addIfAbsent(E e)Appends the element, if not present.
clear()Removes all of the elements from this list.
clone()Returns a shallow copy of this list.
contains(Object o)Returns true if this list contains the specified element.
containsAll(Collection c)Returns true if this list contains all of the elements of the specified collection.
 equals(Object o)Compares the specified object with this list for equality.
 forEach(Consumer action)Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.
 get(int index)Returns the element at the specified position in this list.
 hashCode()Returns the hash code value for this list.
indexOf(E e, int index)Returns the index of the first occurrence of the specified element in this list, searching forwards from the index, or returns -1 if the element is not found.
indexOf(Object o)Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
isEmpty()Returns true if this list contains no elements.
iterator()Returns an iterator over the elements in this list in the proper sequence.
lastIndexOf(E e, int index)Returns the index of the last occurrence of the specified element in this list, searching backward from the index, or returns -1 if the element is not found.
lastIndexOf(Object o)Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
listIterator()Returns a list iterator over the elements in this list (in proper sequence).
listIterator(int index)Returns a list iterator over the elements in this list (in proper sequence), starting at the specified position in the list.
remove(int index)Removes the element at the specified position in this list.
remove(Object o)Removes the first occurrence of the specified element from this list, if it is present.
removeAll(Collection c)Removes from this list all of its elements that are contained in the specified collection.
 removeIf(Predicate filter)Removes all of the elements of this collection that satisfy the given predicate.
replaceAll(UnaryOperator operator)Replaces each element of this list with the result of applying the operator to that element.
retainAll(Collection c)Retains only the elements in this list that are contained in the specified collection.
set(int index, E element)Replaces the element at the specified position in this list with the specified element.
 size()Returns the number of elements in this list.
sort(Comparator c)Sorts this list according to the order induced by the specified Comparator.
spliterator()Returns a Spliterator over the elements in this list.
 subList(int fromIndex, int toIndex)Returns a view of the portion of this list between fromIndex, inclusive, and toIndex, exclusive.
toArray()Returns an array containing all of the elements in this list in proper sequence (from first to the last element).
 toArray(T[] a)Returns an array containing all of the elements in this list in proper sequence (from first to the last element); the runtime type of the returned array is that of the specified array.
 toString()Returns a string representation of this list.

从接口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.

注意:当我们喜欢在并发环境中使用类似于 ArrayList 的数据结构时,我们应该使用CopyOnWriteArrayList

必读:

  • ArrayList 和 CopyOnWriteArrayList 的区别