Java中很少用的CopyOnWriteArrayList

类注释

/**
 * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
 * operations ({@code add}, {@code set}, and so on) are implemented by
 * making a fresh copy of the underlying array.
 * 一个线程安全的ArrayList变量, 其中所有的可变操作(如add, set...) 都会通过创建一个新的当前 
 * 数组的拷贝
 *
 * <p>This is ordinarily too costly, but may be <em>more</em> efficient
 * than alternatives when traversal operations vastly outnumber
 * mutations, and is useful when you cannot or don't want to
 * synchronize traversals, yet need to preclude interference among
 * concurrent threads.  
 * 这通常代价过大, 但是当遍历操作远远超过变化时它会是更有效的, 当你不能或者不想执行同步遍历
 * 时, 你需要通对并发线程进行干预。
 * The "snapshot" style iterator method uses a reference to the state of the array 
 * at the point that the iterator was created. 
 * 快照式的迭代方法在该迭代器被创建时使用了一个指向数组状态的引用。
 * This array never changes during the lifetime of the
 * iterator, so interference is impossible and the iterator is
 * guaranteed not to throw {@code ConcurrentModificationException}.
 * 该数组在此迭代器的生命周期中从未改变, 所以它不可能被干预, 并且此迭代确定不会抛出并发修改
 * 异常。
 *
 * The iterator will not reflect additions, removals, or changes to
 * the list since the iterator was created. 
 * 只要迭代器的创建, 它就不会对此列表的添加, 移除, 改变作出反应。
 * Element-changing operations on iterators themselves ({@code remove}, {@code set}, 
 * and{@code add}) are not supported. 
 * 会改变迭代器自身的元素改变操作不会被支持, 比如remove, set, add等
 * These methods throw {@code UnsupportedOperationException}.
 * 使用这些方法会抛出不支持的操作异常
 *
 * <p>All elements are permitted, including {@code null}.
 * 所有元素都是被允许的, 包括空
 * <p>Memory consistency effects: As with other concurrent
 * collections, actions in a thread prior to placing an object into a
 * {@code CopyOnWriteArrayList}
 * 内存一致性影响, 与其他并发集合相同, 线程中的行为优先于把对象放入CopyOnWriteArrayList中
 * <a href="package-summary.html#MemoryVisibility(内存可见性)"><i>happen-before</i>
 * </a>
 * actions subsequent to the access or removal of that element from
 * the {@code CopyOnWriteArrayList} in another thread.
 * 在从CopyOnWriteArrayList中获取或移除该元素之后的操作在其他线程中进行
 *
 * <p>This class is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <E> the type of elements held in this collection
 */

属性

    private static final long serialVersionUID = 8673264195747942595L;

    /** The lock protecting all mutators 
     * 保护所有突变因子的锁(可重入锁)
     * 注意: transient关键字标记的成员变量不参与序列化过程
     */
    final transient ReentrantLock lock = new ReentrantLock();

    /** The array, accessed only via getArray/setArray. 
     * 对象数组, 只能通过getArray/setArray获取
     */
    private transient volatile Object[] array;

方法

  • Constructor:

    • CopyOnWriteArrayList()

       /**
           * Creates an empty list.
           * 创建空列表
           */
          public CopyOnWriteArrayList() {
              setArray(new Object[0]);
          }
      
    • CopyOnWriteArrayList(Collection<? extends E> c)

      /**
           * Creates a list containing the elements of the specified
           * collection, in the order they are returned by the collection's
           * iterator.
           * 创建一个包含特定集合的元素的列表, 元素排序按集合的迭代器返回的顺序。
           *
           * @param c the collection of initially held elements
           * @throws NullPointerException if the specified collection is null
           */
          public CopyOnWriteArrayList(Collection<? extends E> c) {
              Object[] elements;
              // 如果集合c的类型是CopyOnWriteArrayList的类型
              if (c.getClass() == CopyOnWriteArrayList.class)
                  // 就获取数组
                  elements = ((CopyOnWriteArrayList<?>)c).getArray();
              else {
                  elements = c.toArray();
                  // c.toArray might (incorrectly) not return Object[] (see 6260652)
                  // c.toArray 可能不能正确地返回Object[](请查看issue 6260652)
                  // 如果元素数组类型不是Object数组类型
                  if (elements.getClass() != Object[].class)
                      // 就重新拷贝一份为Object数组类型的元素数组
                      elements = Arrays.copyOf(elements, elements.length, Object[].class);
              }
              setArray(elements);
          }
      
    • CopyOnWriteArrayList(E[] toCopyIn)

      /**
           * Creates a list holding a copy of the given array.
           * 将对象数组设置为获得的数组的拷贝
           *
           * @param toCopyIn the array (a copy of this array is used as the
           *        internal array)
           * @throws NullPointerException if the specified array is null
           */
          public CopyOnWriteArrayList(E[] toCopyIn) {
              setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
          }
      
      
      
    
  • 重要方法

    • set()

       /**
           * Replaces the element at the specified position in this list with the
           * specified element.
           * 替换列表中特定位置的元素为xx
           *
           * @throws IndexOutOfBoundsException {@inheritDoc}
           */
          public E set(int index, E element) {
              // 获取可重入锁
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  // 获取旧值
                  E oldValue = get(elements, index);
      
                  // 如果旧值与传入的元素不相等
                  if (oldValue != element) {
                      int len = elements.length;
                      // 拷贝一份新的元素数组
                      Object[] newElements = Arrays.copyOf(elements, len);
                      // 并将元素传入的元素赋给新的元素数组该位置的值
                      newElements[index] = element;
                      // 将新元素数组赋值给对象数组
                      setArray(newElements);
                  } else {
                      // Not quite a no-op; ensures volatile write semantics
                      // 并不是无操作, 需要确保写语义的可见性
                      setArray(elements);
                }
                  // 返回旧值
                return oldValue;
              } finally {
                  lock.unlock();
              }
          }
      
      
    • add()

      /**
           * Appends the specified element to the end of this list.
           * 将特定的元素添加到此列表尾部
           * @param e element to be appended to this list
           * @return {@code true} (as specified by {@link Collection#add})
           */
          public boolean add(E e) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  // 其实最主要的还是对原数组进行了拷贝
                Object[] newElements = Arrays.copyOf(elements, len + 1);
                  newElements[len] = e;
                setArray(newElements);
                  return true;
            } finally {
                  lock.unlock();
              }
          }
      
      
    • add(int index, E element)

          /**
           * Inserts the specified element at the specified position in this
           * list. 
           * 插入特定的元素到指定的位置 
           * Shifts the element currently at that position (if any) and
           * any subsequent elements to the right (adds one to their indices).
           * 插入后将从该位置开始其后所有的元素的位置右移一位
           *
           * @throws IndexOutOfBoundsException {@inheritDoc}
           */
          public void add(int index, E element) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  // 如果越界就抛异常
                  if (index > len || index < 0)
                      throw new IndexOutOfBoundsException("Index: "+index+
                                                          ", Size: "+len);
                  Object[] newElements;
                  // 需要移动的数量
                  int numMoved = len - index;
                if (numMoved == 0)
                      // 如果就是在最后位置添加, 再拷一个长度+1的数组给赋给新元素数组
                    newElements = Arrays.copyOf(elements, len + 1);
                  else {
                    // 先扩位
                      newElements = new Object[len + 1];
                      // 再将旧元素数组中的值拷贝给新数组
                      System.arraycopy(elements, 0, newElements, 0, index);
                      // 再将从该位置开始其后所有的元素的位置右移一位
                      System.arraycopy(elements, index, newElements, index + 1,
                                       numMoved);
                  }
                  newElements[index] = element;
                  setArray(newElements);
              } finally {
                  lock.unlock();
              }
          }
      
    • E remove(int index)

          /**
           * Removes the element at the specified position in this list.
           * 移除指定位置的元素
           * Shifts any subsequent elements to the left (subtracts one from their
           * indices).  
           * 将该位置后的元素前移
           * Returns the element that was removed from the list.
           * 返回从列表被移除的元素
           * @throws IndexOutOfBoundsException {@inheritDoc}
           */
          public E remove(int index) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                Object[] elements = getArray();
                  int len = elements.length;
                E oldValue = get(elements, index);
                  // 需要前移的元素数量
                  int numMoved = len - index - 1;
                if (numMoved == 0)
                      setArray(Arrays.copyOf(elements, len - 1));
                  else {
                      // 与之前同理
                      Object[] newElements = new Object[len - 1];
                      System.arraycopy(elements, 0, newElements, 0, index);
                      System.arraycopy(elements, index + 1, newElements, index,
                                       numMoved);
                      setArray(newElements);
                  }
                  return oldValue;
              } finally {
                  lock.unlock();
              }
          }
      
    • boolean remove(Object o)

      /**
         * Removes the first occurrence of the specified element from this list,
         * if it is present.  
         * 移除列表中出现的第一个出现的该元素。
         * If this list does not contain the element, it is unchanged.  
         * 如果没有该元素, 就不变
         * More formally, removes the element with the lowest index
         * 更正式地说, 移除参数位置最小的该元素
         * {@code i} such that
           * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
           * (if such an element exists).  
           * Returns {@code true} if this list contained the specified element (or 
           * equivalently, if this list changed as a result of the call).
           * 如果有该元素, 且对象数组被改变, 就返回true
           *
           * @param o element to be removed from this list, if present
           * @return {@code true} if this list contained the specified element
           */
          public boolean remove(Object o) {
              // 获取当前快照
              Object[] snapshot = getArray();
              int index = indexOf(o, snapshot, 0, snapshot.length);
              return (index < 0) ? false : remove(o, snapshot, index);
          }
      
    • boolean remove(Object o, Object[] snapshot, int index)

      /**
           * A version of remove(Object) using the strong hint that given
           * recent snapshot contains o at the given index.
           * 根据已得的包含位置为index的最近的快照, 使用强暗示进行移除?
           */
          private boolean remove(Object o, Object[] snapshot, int index) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] current = getArray();
                  int len = current.length;
                  // 如果快债不是当前快照(findIndex是一个标签, java保留goto部分作用还记得不, break跳转过来的)
                  if (snapshot != current) findIndex: {
                      // 获取前缀
                      int prefix = Math.min(index, len);
                      for (int i = 0; i < prefix; i++) {
                          if (current[i] != snapshot[i] && eq(o, current[i])) {
                              index = i;
                              break findIndex;
                          }
                      }
                      if (index >= len)
                        return false;
                      if (current[index] == o)
                        break findIndex;
                      index = indexOf(o, current, index, len);
                    if (index < 0)
                          return false;
                  }
                  Object[] newElements = new Object[len - 1];
                  System.arraycopy(current, 0, newElements, 0, index);
                  System.arraycopy(current, index + 1,
                                   newElements, index,
                                   len - index - 1);
                  setArray(newElements);
                  return true;
              } finally {
                  lock.unlock();
              }
          }
      
    • removeRange(int fromIndex, int toIndex) 移除哪个区域的元素

        /**
           * Removes from this list all of the elements whose index is between
           * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
           * Shifts any succeeding elements to the left (reduces their index).
           * This call shortens the list by {@code (toIndex - fromIndex)} elements.
           * (If {@code toIndex==fromIndex}, this operation has no effect.)
           *
           * @param fromIndex index of first element to be removed
           * @param toIndex index after last element to be removed
           * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
           *         ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
           */
          void removeRange(int fromIndex, int toIndex) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
      
                  if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
                    throw new IndexOutOfBoundsException();
                  int newlen = len - (toIndex - fromIndex);
                int numMoved = len - toIndex;
                  if (numMoved == 0)
                      setArray(Arrays.copyOf(elements, newlen));
                  else {
                      Object[] newElements = new Object[newlen];
                      System.arraycopy(elements, 0, newElements, 0, fromIndex);
                      System.arraycopy(elements, toIndex, newElements,
                                       fromIndex, numMoved);
                      setArray(newElements);
                  }
              } finally {
                  lock.unlock();
              }
          }
      
  • boolean addIfAbsent() 如果不存在就添加到最后

    /**
         * Appends the element, if not present.
         *
         * @param e element to be added to this list, if absent
         * @return {@code true} if the element was added
         */
        public boolean addIfAbsent(E e) {
            Object[] snapshot = getArray();
            return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
                addIfAbsent(e, snapshot);
        }
    
    • boolean addIfAbsent(E e, Object[] snapshot)

      /**
           * A version of addIfAbsent using the strong hint that given
           * recent snapshot does not contain e.
           * 一个使用了强按时(最近快照中没有e)
           */
          private boolean addIfAbsent(E e, Object[] snapshot) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] current = getArray();
                int len = current.length;
                  if (snapshot != current) {
                    // Optimize for lost race to another addXXX operation
                    // 对另外的添加操作进行损失率优化(这其实有点像动态规划了)  
                      int common = Math.min(snapshot.length, len);
                    for (int i = 0; i < common; i++)
                          if (current[i] != snapshot[i] && eq(e, current[i]))
                            return false;
                      if (indexOf(e, current, common, len) >= 0)
                              return false;
                  }
                  Object[] newElements = Arrays.copyOf(current, len + 1);
                  newElements[len] = e;
                  setArray(newElements);
                  return true;
              } finally {
                  lock.unlock();
              }
          }
      
    • boolean containsAll(Collection<?> c): 包含所有

          /**
           * Returns {@code true} if this list contains all of the elements of the
           * specified collection.
           *
           * @param c collection to be checked for containment in this list
           * @return {@code true} if this list contains all of the elements of the
           *         specified collection
           * @throws NullPointerException if the specified collection is null
           * @see #contains(Object)
           */
          public boolean containsAll(Collection<?> c) {
              Object[] elements = getArray();
              int len = elements.length;
              for (Object e : c) {
                  if (indexOf(e, elements, 0, len) < 0)
                      return false;
              }
              return true;
          }
      
    • boolean removeAll(Collection<?> c): 移除所有

      /**
           * Removes from this list all of its elements that are contained in
           * the specified collection. 
           * 在列表中移除所有集合中包含的元素
           * This is a particularly expensive operation
           * in this class because of the need for an internal temporary array.
           * 因为需要临时数组, 所以开销较大。
           *
           * @param c collection containing elements to be removed from this list
           * @return {@code true} if this list changed as a result of the call
           * @throws ClassCastException if the class of an element of this list
           *         is incompatible with the specified collection
           *         (<a href="../Collection.html#optional-restrictions">optional</a>)
           * @throws NullPointerException if this list contains a null element and the
           *         specified collection does not permit null elements
           *         (<a href="../Collection.html#optional-restrictions">optional</a>),
           *         or if the specified collection is null
           * @see #remove(Object)
           */
          public boolean removeAll(Collection<?> c) {
              if (c == null) throw new NullPointerException();
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  if (len != 0) {
                      // temp array holds those elements we know we want to keep
                      // 使用临时数组维护这些我们想要保留的元素
                      int newlen = 0;
                      Object[] temp = new Object[len];
                      for (int i = 0; i < len; ++i) {
                          Object element = elements[i];
                          if (!c.contains(element))
                              temp[newlen++] = element;
                      }
                      if (newlen != len) {
                          setArray(Arrays.copyOf(temp, newlen));
                          return true;
                      }
                  }
                  return false;
              } finally {
                  lock.unlock();
              }
          }
      
    • boolean retainAll(Collection<?> c)

      /**
           * Retains only the elements in this list that are contained in the
           * specified collection.  
           * 在列表中保留所有该特定集合中含有的元素。
           * 
           * In other words, removes from this list all of its elements that are 
           * not contained in the specified collection.
           * 也就是会将所有不在该集合中的元素移除(说白了取交集)
           *
           * @param c collection containing elements to be retained in this list
           * @return {@code true} if this list changed as a result of the call
           * @throws ClassCastException if the class of an element of this list
           *         is incompatible with the specified collection
           *         (<a href="../Collection.html#optional-restrictions">optional</a>)
           * @throws NullPointerException if this list contains a null element and the
           *         specified collection does not permit null elements
           *         (<a href="../Collection.html#optional-restrictions">optional</a>),
           *         or if the specified collection is null
           * @see #remove(Object)
           */
          public boolean retainAll(Collection<?> c) {
              if (c == null) throw new NullPointerException();
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  if (len != 0) {
                      // temp array holds those elements we know we want to keep
                      // 使用临时数组维护这些我们想要保留的元素
                      int newlen = 0;
                      Object[] temp = new Object[len];
                      for (int i = 0; i < len; ++i) {
                          Object element = elements[i];
                          if (c.contains(element))
                              temp[newlen++] = element;
                      }
                      if (newlen != len) {
                          setArray(Arrays.copyOf(temp, newlen));
                          return true;
                      }
                  }
                  return false;
              } finally {
                  lock.unlock();
              }
          }
      
原文地址:https://www.cnblogs.com/ronnieyuan/p/12148280.html