`

集合框架 List篇(2)---CopyOnWriteArrayList

 
阅读更多
List
-----------
1.ArrayList(jdk1.5以前版本中Vector)
2.LinkedList(jdk1.5以前版本中Stack)
3.CopyOnWriteArrayList

----------------------------------------CopyOnWriteArrayList----------------------------------------

CopyOnWriteArrayList 用在“读多,改少”的“并发”应用中。

不存在“扩容”的概念,每次写操作(add or remove)都要copy一个副本,在副本的基础上修改后改变array引用---所以称为“CopyOnWrite”,因此在写操作是加锁,并且对整个list的copy操作时相当耗时的,过多的写操作不推荐使用该存储结构。

CopyOnWriteArrayList的类层次结构
public class CopyOnWriteArrayList <E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 

CopyOnWriteArrayList的全局变量

 transient final ReentrantLock lock = new ReentrantLock();//全局锁

 private volatile transient Object[] array;//volatile(修改可见)类型的数组array

//内部的实现中仅通过array的get和set方法对其进行操作

 final Object[] getArray() {
        return array;
  }

  final void setArray(Object[] a) {
        array = a;
  }

CopyOnWriteArrayList的构造方法
   /**
     * 创建一个空的list,默认容量为0,这个和ArraList中的默认10不同,主要是因为在对CopyOnWriteArrayList的修改操作时都是先copy

     *一个数组(容量+1或容量-1),处理后再把引用赋给array的,不存在扩容的情况,所以当初始化时就没必要指定长度了。

     */
    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }

 //通过已有集合构建CopyOnWriteArrayList

 public CopyOnWriteArrayList(Collection<? extends E> c) {
    Object[] elements = c.toArray();
     if (elements.getClass() != Object[].class)
           elements = Arrays.copyOf(elements, elements.length, Object[].class);//copy一个数组
    setArray(elements);//把array引用指向新的数组
  }

  //通过给定的数组创建List

 public CopyOnWriteArrayList(E[] toCopyIn) {
     setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
 }

CopyOnWriteArrayList的get方法

//get操作 ,不加锁

public E get(int index) {
      //直接定位到数组的index下标处,没有加锁操作

      //(array是volatile类型的,volatile的 happen-before原则就是所有的“写操作”都在“读操作”前发生,保证了数据的一致性) 

        return (E)(getArray()[index]);

 } 

CopyOnWriteArrayList的set方法

//set 修改元素操作,加锁

public E set(int index, E element) {//在指定的位置index处设置element
 final ReentrantLock lock = this.lock;
 lock.lock();//加锁
 try {
     Object[] elements = getArray();
     Object oldValue = elements[index];//获得数组中index坐标下的值

     if (oldValue != element) {//如果传入的element和目前坐标index处的值不同
         int len = elements.length;
         Object[] newElements = Arrays.copyOf(elements, len);//copy一个数组副本
         newElements[index] = element;//并把指定index处的值进行替换
         setArray(newElements);//array引用指向新的数组
     } else {
        // Not quite a no-op; ensures volatile write semantics
       setArray(elements);//保证volatile的happen-before原则
    }
   return (E)oldValue;
 } finally {
     lock.unlock();//解锁
 }
}


CopyOnWriteArrayList的add方法

//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;//在新数组的最后一个位置加入e元素
          setArray(newElements);
          return true;
       } finally {
         lock.unlock();//解锁
      }
    }

 //在指定的index处加入元素element,加锁

 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)//刚好在末端加入的情况
                 newElements = Arrays.copyOf(elements, len + 1);
        else {//在中间的情况
                newElements = new Object[len + 1];
               System.arraycopy(elements, 0, newElements, 0, index);//index前的元素
               System.arraycopy(elements, index, newElements, index + 1, numMoved);//index后的元素
        }
     newElements[index] = element;
     setArray(newElements);
 } finally {
     lock.unlock();//解锁
 }
}
CopyOnWriteArrayList的remove方法

//remove 删除操作,加锁

public E remove(int index) {
     final ReentrantLock lock = this.lock;
     lock.lock();//加锁
     try {
         Object[] elements = getArray();
         int len = elements.length;
         Object oldValue = 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 (E)oldValue;
    } finally {
        lock.unlock();//解锁
    }
  }

//remove参数是元素对象,需要遍历比较,加锁

public boolean remove(Object o) {
     final ReentrantLock lock = this.lock;
     lock.lock();//加锁
     try {
         Object[] elements = getArray();
         int len = elements.length;
         if (len != 0) {
                // Copy while searching for element to remove
                // This wins in the normal case of element being present
               int newlen = len - 1;
              Object[] newElements = new Object[newlen];//创建一个length-1的数组

              for (int i = 0; i < newlen; ++i) {
                      if (eq(o, elements[i])) {
                         // 如果找到了该元素,就把其后继拷贝到新数组中

                         for (int k = i + 1; k < len; ++k)
                                newElements[k-1] = elements[k];
                         setArray(newElements);
                         return true;
                       } else

                         //把其前面的节点一一设置到新数组中去
                         newElements[i] = elements[i];
                       }

                     // 特殊的判断:和最和一个元素比较(如果刚好是最后一个,就大大减少比较)

                     if (eq(o, elements[newlen])) {
                           setArray(newElements);
                           return true;
                      }
            }
        return false;
   } finally {
       lock.unlock();//解锁
   }

}
分享到:
评论

相关推荐

    11.集合框架001-Collection接口1-3

    接下来,我们转向“2-集合框架002-List接口-1080P 高清-AVC.mp4”。List接口是Collection的一个子接口,它增加了索引访问的能力,使得元素可以根据其位置被引用。ArrayList是List接口的一个具体实现,基于动态数组。...

    集合框架学习笔记

    这篇学习笔记将深入探讨Java集合框架的基础概念、主要类库以及常见应用场景。 首先,Java集合框架分为两种基本类型:List(列表)和Set(集)。List接口代表有序的集合,允许重复元素,如ArrayList和LinkedList;而...

    11.集合框架001-Collection接口4-5

    2. **泛型**:描述在4-集合框架004-集合中的泛型中讲解的内容,泛型是Java SE 5.0引入的一个重要特性。泛型允许在集合中声明元素类型,增强了类型安全性和代码可读性。例如,我们可以创建一个只存储String类型的...

    集合框架总结图

    集合框架是Java编程语言中的一个核心部分,它提供了一套高效、灵活的数据结构和算法,使得开发者能够方便地管理和操作对象。本总结图详细而全面地涵盖了Java集合框架的主要概念和组件,对于初学者和有经验的开发人员...

    学士后Java集合框架和泛型课后习题答案

    在Java中,集合框架主要包括接口(如List、Set、Queue)和实现这些接口的类(如ArrayList、HashSet、LinkedList等)。这个框架允许我们高效地处理各种数据结构,而无需从头开始编写代码。泛型则是Java 5引入的一项...

    08-《集合框架-1》.rar

    Java集合框架主要分为两大接口:List和Set。List接口代表有序的、可重复的元素集合,如ArrayList和LinkedList;而Set接口则代表无序且不允许重复元素的集合,如HashSet。此外,Map接口用于存储键值对,如HashMap,它...

    Java集合框架详解

    集合框架是一个统一的数据结构模型,它定义了一系列接口,如Collection、List、Set和Map,以及它们的实现类,如ArrayList、LinkedList、HashSet、HashMap等。容器是这些接口和类的统称,它们用于存储和管理对象。...

    集合框架源码分析

    Java集合框架主要包括`Collection`、`List`、`Set`和`Map`四大接口。`Collection`是最基本的接口,`List`和`Set`继承自它。`List`接口保持元素的顺序,并允许重复元素;`Set`接口则不允许重复元素,且不保证元素的...

    Java 集合框架介绍.ppt

    - 针对多线程环境,Java集合框架提供了线程安全的实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`等,它们在并发环境下提供了更高的性能。 7. **扩展和高级特性**: - `LinkedHashSet`和`...

    advanced-java-collections:高级Java课程-集合框架的源代码-Source code collection

    Java集合框架中的`ConcurrentHashMap`和`CopyOnWriteArrayList`等类设计用于多线程环境,提供了线程安全的访问。 5. **源码分析**: 深入源码可以发现,例如ArrayList的扩容策略、HashMap的冲突解决以及...

    java集合框架

    - `Collection`:集合框架的顶级接口,所有单列集合(如List、Set)的父接口。 - `List`:有序、可重复的元素集合,支持索引访问,如ArrayList和LinkedList。 - `Set`:不允许重复元素的集合,如HashSet和TreeSet...

    Java集合框架的知识总结.doc

    本篇文章将对Java集合框架进行深入的总结,包括其核心接口、类以及常用方法。 1. **集合框架概述** Java集合框架的核心接口主要有两个:`Collection`和`Map`。`Collection`接口是所有单值容器的基接口,如`List`、...

    数据结构和Java集合框架

    数据结构和Java集合框架是Java编程中至关重要的概念,它们是高效编程和算法设计的基础。在Java中,数据结构指的是组织、存储和管理数据的方式,而集合框架则是一组接口和类,为处理各种数据结构提供了统一的API。 ...

    Java集合框架常见面试题.pdf

    Java集合框架还提供了一些高级特性和工具类,如CopyOnWriteArrayList、ConcurrentHashMap等,它们在多线程环境下提供了更好的性能和安全性。另外,迭代器(Iterator)是遍历集合的重要工具,它定义了hasNext()和next...

    集合框架代码及PPT、API.rar

    2. **集合框架中的接口** - **List接口**:代表有序的元素集合,允许有重复元素。ArrayList和LinkedList是它的主要实现类。 - **Set接口**:不允许有重复元素,提供了HashSet和TreeSet等实现。 - **Queue接口**:...

    Java-collection-frame.rar_Java集合框架

    在Java集合框架中,主要分为两大类:List(列表)、Set(集合)和Map(映射)。 1. List接口:List是一种有序的集合,允许包含重复元素。它定义了元素的插入、删除和访问方法,如add()、remove()和get()。ArrayList...

    Java_集合框架_课件

    Java集合框架还包括并发集合,如`ConcurrentHashMap`、`CopyOnWriteArrayList`和`CopyOnWriteArraySet`,它们在多线程环境下提供高并发性能。 8. **流API**: 自Java 8起,引入了流API(Stream API),提供了一种...

    Java集合框架常见面试题.7z

    Java集合框架是Java编程语言中的一个核心组件,它为存储、管理和操作对象提供了一组统一的接口和类。面试中,对于Java开发者来说,对集合框架的理解和熟练应用通常是评估其技能的重要方面。以下是一些关于Java集合...

    全面接触Java集合框架

    Java集合框架是Java编程语言中不可或缺的一部分,它提供了一种高效、灵活的方式来存储和操作数据。这个框架包括了各种接口和类,它们为开发者提供了多种数据结构,如数组、链表、队列、堆栈、映射等。下面将详细探讨...

    java集合框架PPT

    1. **集合接口**:集合框架的核心是若干个接口,包括`List`、`Set`、`Queue`和`Map`。这些接口定义了各种数据结构的行为,如有序列表、无重复元素集合、队列以及键值对映射。 - `List`接口:线性结构,元素有顺序...

Global site tag (gtag.js) - Google Analytics