类注释

/**
* 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();
      }
      }

Java中很少用的CopyOnWriteArrayList的更多相关文章

  1. DELPHI语法基础学习笔记-Windows 句柄、回调函数、函数重载等(Delphi中很少需要直接使用句柄,因为句柄藏在窗体、 位图及其他Delphi 对象的内部)

    函数重载重载的思想很简单:编译器允许你用同一名字定义多个函数或过程,只要它们所带的参数不同.实际上,编译器是通过检测参数来确定需要调用的例程.下面是从VCL 的数学单元(Math Unit)中摘录的一 ...

  2. 为什么函数式编程在Java中很危险?

    摘要:函数式编程这个不温不火的语言由来已久.有人说,这一年它会很火,尽管它很难,这也正是你需要学习的理由.那么,为什么函数式编程在Java中很危险呢?也许这个疑问普遍存在于很多程序员的脑中,作者Ell ...

  3. Java 编程语言中很少被人了解的特性-statement label

    下面的语句会编译报错或者打印什么? System.out.print("baidu site :"); https://www.baidu.com; System.out.prin ...

  4. java入门书籍很少介绍的java知识

    1.java中数组的长度可以用.length来确定 2.java中的Arrays类可以对数组进行轻松的操作 (1).包名:import java.util.Arrays (2).Arrays.sort ...

  5. 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。

    我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...

  6. [Java类加载器]Java中classLoader浅析.

    本文为在公司内部TD上写的一篇小文, 主要讲解java中classLoader基础知识, 现在拿来这里分享一下. 一.问题 请在Eclipse中新建如下类,并运行它: 1 package java.l ...

  7. Java 中的日期与时间

    Java 日期时间 标签 : Java基础 Date java.util.Date对象表示一个精确到毫秒的瞬间; 但由于Date从JDK1.0起就开始存在了,历史悠久,而且功能强大(既包含日期,也包含 ...

  8. java 中的基本数据类型

    1,  变量 Java是强类型语言, 对于每一种数据都定义了类型,基本数据类型分为数值型,字符型,布尔型.数值型又分为了整型和浮点型. 整型又分为byte, int, short long. 浮点型又 ...

  9. Java 中 == 和 equals 的区别

    有一段时间,== 和 equals 的区别一直困扰着我.因为涉及到Java的内存机制,然而Java的内存机制又是比较抽象的东西,所以对那时候的我来说,实在是很难理解. == 和 equals 最大的区 ...

随机推荐

  1. Flexconnect部署

    该记录主要用于针对于无线网络中Flexconnect的部署,可能涉及到的有Flexconnect中的组件,如何部署.(注意:在7.2版本以前,Flexconnect叫做HREAP),目前都称作为Fle ...

  2. MariaDB-Galera部署

    Galera Cluster:集成了Galera插件的MySQL集群,是一种新型的,数据不共享的,高度冗余的高可用方案,目前Galera Cluster有两个版本,分别是Percona Xtradb ...

  3. Jquery实现ajax常用属性

  4. php 基础 语句include和require的区别是什么?为避免多次包含同一文件,可用(?)语句代替它们?

    require->require是无条件包含也就是如果一个流程里加入require,无论条件成立与否都会先执行 require include->include有返回值,而require没 ...

  5. map中entrySet和KeySet的区别

  6. springboot中关于datasource的配置

    datasource spring.dao.exceptiontranslation.enabled: 是否开启PersistenceExceptionTranslationPostProcessor ...

  7. SSM日常报错

    mybatis配置时出现org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 解决方法: po ...

  8. python的datetime、random和os模块使用方法

    import datetime# print(datetime.date.today())# print(datetime.datetime.today())# res=datetime.dateti ...

  9. 吴裕雄--天生自然 JAVA开发学习:java使用Eclipel连接数据库

    1:jar可到Mysql官网下载:地址Mysql 连接jar包.:https://dev.mysql.com/downloads/connector/j/如图,在下拉列表框中选择Platform In ...

  10. 吴裕雄--天生自然ORACLE数据库学习笔记:数据导出与导入

    create directory dump_dir as 'd:\dump'; grant read,write on directory dump_dir to scott; --在cmd下 exp ...