天天看點

JDK8源碼閱讀(十一) CopyOnWriteArrayList TODO一、簡介二、分析

一、簡介

二、分析

2.1 類結構

2.1.0 類結構圖

  • JDK8源碼閱讀(十一) CopyOnWriteArrayList TODO一、簡介二、分析

2.2 内部類

2.2.0 内部類清單圖

  • JDK8源碼閱讀(十一) CopyOnWriteArrayList TODO一、簡介二、分析

2.2.1 COWIterator

/**
     * 靜态内部類疊代器COWIterator
     */
    static final class COWIterator<E> implements ListIterator<E> {
        // 内部數組快照
        private final Object[] snapshot;
        // 疊代器開始周遊的索引  周遊的是子數組
        private int cursor;

        // 構造函數,指定數組和開始周遊索引位置
        private COWIterator(Object[] elements, int initialCursor) {
            cursor = initialCursor;
            snapshot = elements;
        }

        // 判斷是否有後繼元素
        public boolean hasNext() {
            // 索引是否小于快照的長度
            return cursor < snapshot.length;
        }

        // 是否有前驅元素
        public boolean hasPrevious() {
            // 光标大于0 則有 否則沒有
            return cursor > 0;
        }

        // 擷取下個元素
        @SuppressWarnings("unchecked")
        public E next() {
            // 檢驗是否還有下個元素
            if (! hasNext())
                throw new NoSuchElementException();
            // 傳回下個元素,并将光标自增
            return (E) snapshot[cursor++];
        }

        // 擷取前驅元素
        @SuppressWarnings("unchecked")
        public E previous() {
            // 校驗是否有前驅元素
            if (! hasPrevious())
                throw new NoSuchElementException();
            // 傳回前驅元素,并将光标索引遞減
            return (E) snapshot[--cursor];
        }

        // 擷取下個元素的索引位置 也就是目前光标
        public int nextIndex() {
            return cursor;
        }

        // 擷取上一個元素的索引位置
        public int previousIndex() {
            // 目前光标減1
            return cursor-1;
        }

        /**
         * 過時方法,不再支援
         */
        public void remove() {
            throw new UnsupportedOperationException();
        }

        /**
         * 過時方法,不再支援
         */
        public void set(E e) {
            throw new UnsupportedOperationException();
        }

        /**
         * 過時方法,不再支援
         */
        public void add(E e) {
            throw new UnsupportedOperationException();
        }

        
        /**
         * 提供JDK8的lambda方式周遊 TODO
         */    
        @Override
        public void forEachRemaining(Consumer<? super E> action) {
            // 檢驗非空
            Objects.requireNonNull(action);
            // 備份數組并擷取長度
            Object[] elements = snapshot;
            final int size = elements.length;
            // TODO
            for (int i = cursor; i < size; i++) {
                @SuppressWarnings("unchecked") E e = (E) elements[i];
                action.accept(e);
            }
            cursor = size;
        }
    }
           

2.2.2 COWSubList

2.2.3 COWSubListIterator

2.3 字段

2.3.0 字段清單圖

  • JDK8源碼閱讀(十一) CopyOnWriteArrayList TODO一、簡介二、分析

2.3.1 array

  • /**
     * 内部維護的數組集合,隻能通過getArray或setArray來通路
     */
    private transient volatile Object[] array;
               

2.3.2 lock 

  • /**
     * 内部采用獨占鎖ReetrantLock來保證并發操作
     */
    final transient ReentrantLock lock = new ReentrantLock();
               

2.3.3 lockOffset

/**
 * lock鎖的在該類中的偏移量,友善Unsafe類進行cas操作
 */
private static final long lockOffset;
           

2.2.4 UNSAFE

/**
 * 用來進行CAS操作的類
 */
private static final sun.misc.Unsafe UNSAFE;
           

2.4 代碼塊

2.4.1 靜态代碼塊

/**
     * 使用Unsafe的方法擷取到lock字段的偏移量用于cas操作
     */
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> k = CopyOnWriteArrayList.class;
            lockOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("lock"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }
           

2.5 方法

2.5.0 方法清單圖

  • JDK8源碼閱讀(十一) CopyOnWriteArrayList TODO一、簡介二、分析
  • JDK8源碼閱讀(十一) CopyOnWriteArrayList TODO一、簡介二、分析

2.5.1 構造函數

/**
     * 無參構造函數,預設調用setArray方法将内部維護的數組初始化一個長度為0的數組集合
     */
    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }

    
    /**
     * 接收一個Collection類型的集合的構造函數。
     * 如果該類是CopyOnWriteArrayList,則直接調用getArray方法拿到數組并通過setArray方法設定到内部維護的資料中
     * 如果不是,則直接調用toArray()方法拿到數組,然後設定。如果toArray()方法傳回的不是數組,則再調用Arrays工具類的copyOf方法進行複制
     */
    public CopyOnWriteArrayList(Collection<? extends E> c) {
        Object[] elements;
        if (c.getClass() == CopyOnWriteArrayList.class)
            elements = ((CopyOnWriteArrayList<?>)c).getArray();
        else {
            elements = c.toArray();
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elements.getClass() != Object[].class)
                elements = Arrays.copyOf(elements, elements.length, Object[].class);
        }
        setArray(elements);
    }


    /**
     * 接收一個數組的構造參數,内部調用Arrays類個copyOf方法進行拷貝數組
     */
    public CopyOnWriteArrayList(E[] toCopyIn) {
        setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
    }

    
    
           

2.5.2 getArray()

/**
     * 擷取内部維護的數組
     */
    final Object[] getArray() {
        return array;
    }
           

2.5.3 setArray(Object[] a)

/**
     * 設定内部維護的數組
     */
    final void setArray(Object[] a) {
        array = a;
    }
           

2.5.4 size()

/**
     * 傳回目前維護的數組的長度
     */
    public int size() {
        return getArray().length;
    }
           

2.5.5 isEmpty()

/**
     * 判斷該目前維護的數組的長度是否為0
     */
    public boolean isEmpty() {
        return size() == 0;
    }
           

2.5.6 eq(Object o1, Object o2)

/**
     * 比較倆個對象是否相等,包含null
     */
    private static boolean eq(Object o1, Object o2) {
        return (o1 == null) ? o2 == null : o1.equals(o2);
    }
           

2.5.7 indexOf(Object o, Object[] elements, int index, int fence)

/**
     * 查詢元素在指定數組中在index索引到fence索引之間是否存在,如果存在,則傳回索引,不存在,傳回-1
     * 元素可以為null
     */
    private static int indexOf(Object o, Object[] elements,
                               int index, int fence) {
        if (o == null) {
            for (int i = index; i < fence; i++)
                if (elements[i] == null)
                    return i;
        } else {
            for (int i = index; i < fence; i++)
                if (o.equals(elements[i]))
                    return i;
        }
        return -1;
    }
           

2.5.8 lastIndexOf(Object o, Object[] elements, int index)

/**
     * 判斷對象O在資料elements上index索引前最後一次出現的位置,如果有,則傳回索引,否則傳回-1
     */ 
    private static int lastIndexOf(Object o, Object[] elements, int index) {
        if (o == null) {
            for (int i = index; i >= 0; i--)
                if (elements[i] == null)
                    return i;
        } else {
            for (int i = index; i >= 0; i--)
                if (o.equals(elements[i]))
                    return i;
        }
        return -1;
    }
           

2.5.9 contains(Object o)

/**
     * 判斷目前數組是否包含元素O 
     */
    public boolean contains(Object o) {
        Object[] elements = getArray();
        return indexOf(o, elements, 0, elements.length) >= 0;
    }
           

2.5.10 indexOf(Object o)

/**
     * 查詢對象O在目前數組中的索引,如果有傳回索引,沒有傳回-1
     */
    public int indexOf(Object o) {
        Object[] elements = getArray();
        return indexOf(o, elements, 0, elements.length);
    }
           

2.5.11 indexOf(E e, int index)

/**
     * 查詢元素E在目前數組中從索引index處開始首次出現的位置, 如果有,傳回索引,沒有,傳回-1
     */
    public int indexOf(E e, int index) {
        Object[] elements = getArray();
        return indexOf(e, elements, index, elements.length);
    }
           

2.5.12 lastIndexOf(Object o)

/**
     * 查詢對象O在目前數組中最後出現的位置索引,有傳回,沒有傳回-1
     */ 
    public int lastIndexOf(Object o) {
        Object[] elements = getArray();
        return lastIndexOf(o, elements, elements.length - 1);
    }
           

2.5.13 lastIndexOf(E e, int index)

/**
     * 擷取元素e在目前數組中指定index索引之前最後出現的位置索引,如果有,傳回,否則傳回-1
     */
    public int lastIndexOf(E e, int index) {
        Object[] elements = getArray();
        return lastIndexOf(e, elements, index);
    }
           

2.5.14 clone()

/**
     * 調用Object的clone()方法進行淺拷貝, 内部元素并沒有拷貝
     * 然後調用resetLock()方法在指定的lock偏移量位置重新new了一個ReentrantLock對象,重置鎖
     */
    public Object clone() {
        try {
            @SuppressWarnings("unchecked")
            CopyOnWriteArrayList<E> clone = (CopyOnWriteArrayList<E>) super.clone();
            clone.resetLock();
            return clone;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    }
           

2.5.15 resetLock()

/**
     * 重置ReentrantLock鎖
     */
    private void resetLock() {
        UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
    }
           

2.5.16 toArray()

/**
     * 傳回一個數組,内部調用Arrays工具類的copuOff方法
     */
    public Object[] toArray() {
        Object[] elements = getArray();
        return Arrays.copyOf(elements, elements.length);
    }
           

2.5.17  toArray(T a[])

/**
     * 如果目标數組的長度小于内部維護數組的長度,則直接調用Arrays的copyOf方法拷貝;
     * 否則: 先調用System.arraycopy方法進行拷貝,如果目标數組的長度大于内部維護數組的長度,則将目标數組置空 
     * ??? 為啥如果長達大了不直接置空
     */
    public <T> T[] toArray(T a[]) {
        Object[] elements = getArray();
        int len = elements.length;
        if (a.length < len)
            return (T[]) Arrays.copyOf(elements, len, a.getClass());
        else {
            System.arraycopy(elements, 0, a, 0, len);
            if (a.length > len)
                a[len] = null;
            return a;
        }
    }
           

2.5.18 get(Object[] a, int index)

/**
     * 擷取數組中指定索引的元素對象
     */
    private E get(Object[] a, int index) {
        return (E) a[index];
    }
           

2.5.19 get(int index)

/**
     * 擷取内部維護的數組指定索引的元素
     */
    public E get(int index) {
        return get(getArray(), index);
    }
           

2.5.20 set(int index, E element)

/**
     * 修改内部維護數組指定索引處的對象為新對象,并傳回舊對象
     */
    public E set(int index, E element) {
        // 擷取内部的獨占鎖ReentrantLock 
        final ReentrantLock lock = this.lock;
        // 加鎖
        lock.lock();

        try {
            // 拿到内部的數組,并擷取到指定索引的舊對象
            Object[] elements = getArray();
            E oldValue = get(elements, index);

            // 如果不一樣,則使用Arrays類的copyOf方法拿到新數組,然後替換,并更新重新放回即可
            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();
        }
    }
           

2.5.21 add(E e)

/**
     * 添加元素
     */
    public boolean add(E e) {
        // 擷取到獨占鎖ReentrantLock 并加鎖
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 擷取到内部的數組和長度
            Object[] elements = getArray();
            int len = elements.length;
            // 使用Arrays的copyOf方法将原數組拷貝到新數組,長度加一
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            // 将新加的索引位置的元素置為新加的元素 
            newElements[len] = e;
            // 放回數組
            setArray(newElements);
            return true;
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.5.22 add(int index, E element)

/**
     * 在指定索引出添加元素
     */   
    public void add(int index, E element) {
        // 擷取獨占鎖ReentranntLock,并加鎖
        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;
            // 如果是在最後位置添加元素,則調用Arrays的copyOf方法将數組複制,并長度加一
            if (numMoved == 0)
                newElements = Arrays.copyOf(elements, len + 1);
            else {
                // 否則,将新數組長度置為舊數組長度加1
                newElements = new Object[len + 1];
                // 調用System的arraycopy方法将添加位置之前的元素拷貝到新數組
                System.arraycopy(elements, 0, newElements, 0, index);
                // 調用System的arraycopy方法将添加位置之後的元素拷貝到新數組
                System.arraycopy(elements, index, newElements, index + 1,
                                 numMoved);
            }
            // 更新指定索引位置的元素
            newElements[index] = element;
            // 放回内部維護的數組
            setArray(newElements);
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.5.23 remove(int index)

/**
     * 删除指定索引處的元素
     */
    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)
                // 調用Arrays的copyOf方法将舊數組拷貝到新數組,最後一個不拷貝,然後寫回内部維護的數組
                setArray(Arrays.copyOf(elements, len - 1));
            else {
                // 如果删除的不是最後一個元素,則建立新數組,長度為舊數組長度減1
                Object[] newElements = new Object[len - 1];
                // 将删除元素前面的元素調用System.arraycopy方法拷貝到新數組
                System.arraycopy(elements, 0, newElements, 0, index);
                // 将删除元素後面的元素調用System.arraycopy方法拷貝到新數組
                System.arraycopy(elements, index + 1, newElements, index,
                                 numMoved);
                // 寫回内部維護的數組
                setArray(newElements);
            }
            return oldValue;
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.5.24 remove(Object o)

/**
     * 删除元素
     */
    public boolean remove(Object o) {
        // 擷取内部維護數組的快照
        Object[] snapshot = getArray();
        // 擷取元素O在快照中的索引位置
        int index = indexOf(o, snapshot, 0, snapshot.length);
        // 如果不存在,則傳回false,存在,則調用下面的remove方法進行删除
        return (index < 0) ? false : remove(o, snapshot, index);
    }
           

2.5.25 remove(Object o, Object[] snapshot, int index)

/**
     * 将數組snapshot中指定index索引的資料或者指定對象O删除
     * 如果傳遞的數組和目前維護的數組相同,則删除指定索引的元素,否則删除内部維護數組的對象O
     * 注意:如果後者
     */
    private boolean remove(Object o, Object[] snapshot, int index) {
        // 使用獨占鎖ReentrantLock加鎖
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 備份目前數組
            Object[] current = getArray();
            // 記錄目前數組長度
            int len = current.length;

            // 如果傳遞的數組和内部維護的數組不同,則根據對象O查詢索引進行删除
            if (snapshot != current) findIndex: {
                // 擷取倆個數組的長度最小值 
                int prefix = Math.min(index, len);
                // 周遊擷取對象O在内部維護數組的索引
                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;
            }

            // 建立一個新數組,長度比原數組長度少1
            Object[] newElements = new Object[len - 1];
            // 調用System.arraycopy方法進行分倆次将備份數組拷貝到新建立的數組中
            System.arraycopy(current, 0, newElements, 0, index);
            System.arraycopy(current, index + 1, newElements, index, len - index - 1);

            // 寫回内部數組
            setArray(newElements);

            return true;
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.2.26 removeRange(int fromIndex, int toIndex)

/**
     * 删除索引在formIndex和toIndex之間的數組元素
     */
    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;

            // 如果倆個索引相同,則調用Arrays.copyOf方法将備份數組寫回即可
            if (numMoved == 0)
                setArray(Arrays.copyOf(elements, newlen));
            else {
                // 建立新數組
                Object[] newElements = new Object[newlen];
                // 調用System類的arraycopy方法分倆次将數組拷貝到新數組中
                System.arraycopy(elements, 0, newElements, 0, fromIndex);
                System.arraycopy(elements, toIndex, newElements,                          fromIndex, numMoved);
                // 寫回内部數組
                setArray(newElements);
            }
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.2.27 addIfAbsent(E e)

/**
     * 如果目前元素在數組中不存在,則調用addIfAbsent方法進行删除,否則傳回false
     */
    public boolean addIfAbsent(E e) {
        // 備份數組快照
        Object[] snapshot = getArray();
        // 如果存在,則傳回false,否則删除
        return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
            addIfAbsent(e, snapshot);
    }
           

2.2.28 addIfAbsent(E e, Object[] snapshot)

/**
     * 如果元素在快照中不存在,則添加,否則,傳回false
     */
    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);
                // 周遊,快照中如果元素在0~common索引之間存在則傳回false
                for (int i = 0; i < common; i++)
                    if (current[i] != snapshot[i] && eq(e, current[i]))
                        return false;
                // 如果快照中元素在common,len之間存在,也傳回false
                if (indexOf(e, current, common, len) >= 0)
                        return false;
            }

            // 建立新長度的數組,長度比之前大1,并将新增元素添加
            Object[] newElements = Arrays.copyOf(current, len + 1);
            newElements[len] = e;

            // 寫回内部維護數組
            setArray(newElements);
            return true;
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.2.29 containsAll(Collection<?> c)

/**
     * 判斷内部維護的數組是否包含傳入集合的所有元素
     */
    public boolean containsAll(Collection<?> c) {
        // 備份數組并記錄長度
        Object[] elements = getArray();
        int len = elements.length;
        // 周遊傳遞過來的集合中的元素,檢視是否在快照中存在,有一個不存在就傳回false
        for (Object e : c) {
            if (indexOf(e, elements, 0, len) < 0)
                return false;
        }
        // 如果元素都存在則傳回true
        return true;
    }
           

2.2.30 removeAll(Collection<?> c)

/**
     * 删除内部數組中在傳遞數組中的所有元素
     */ 
    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();
        }
    }
           

2.2.31 retainAll(Collection<?> c)

/**
     * 擷取内部數組和目标數組的交集,并寫回到内部數組
     */
    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) {
                // 建立一個新數組用來儲存希望保留的元素
                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();
        }
    }
           

2.2.32 addAllAbsent(Collection<? extends E> c) 

/**
     * 将目标集合中不存在的元素添加的内部維護的數組中 取并集
     */
    public int addAllAbsent(Collection<? extends E> c) {
        // 将目标集合轉換為數組并校驗長度
        Object[] cs = c.toArray();
        if (cs.length == 0)
            return 0;

        // 加獨占鎖
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 備份内部數組并擷取長度
            Object[] elements = getArray();
            int len = elements.length;
            int added = 0;
        
            // uniquify and compact elements in cs
            // 周遊目标數組
            for (int i = 0; i < cs.length; ++i) {
                Object e = cs[i];
                // 如果目标數組中的對象在備份的内部數組中不存在并且在目标數組之前沒有出現過
                if (indexOf(e, elements, 0, len) < 0 &&
                    indexOf(e, cs, 0, added) < 0)
                    cs[added++] = e;
            }
            // added大于0說明存在并集元素
            if (added > 0) {
                // 建立新數組,将原備份數組拷貝進去,并将長度修改為并集的長度
                Object[] newElements = Arrays.copyOf(elements, len + added);
                // 将目标數組從0角标開始拷貝added個元素到新數組的len角标後面
                System.arraycopy(cs, 0, newElements, len, added);
                // 寫回
                setArray(newElements);
            }
            // 傳回添加的元素個數
            return added;
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.2.33 clear()

/**
     * 清空數組
     */
    public void clear() {
        // 加獨占鎖
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 将一個長度為0的數組寫回
            setArray(new Object[0]);
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.2.34 addAll(Collection<? extends E> c)

/**
     * 将目标集合添加到目前集合中
     */
    public boolean addAll(Collection<? extends E> c) {

        // 擷取參數集合的内部數組
        Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ?
            ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();
        // 長度校驗
        if (cs.length == 0)
            return false;

        // 加鎖
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 備份内部數組、擷取長度
            Object[] elements = getArray();
            int len = elements.length;
            // 如果此時内部備份數組長度為0,則将參數數組寫回到内部維護的數組中
            if (len == 0 && cs.getClass() == Object[].class)
                setArray(cs);
            else {
                // 建立一個新數組,元素為備份數組,長度為倆者之和
                Object[] newElements = Arrays.copyOf(elements, len + cs.length);
                // 将目标數組拷貝到新數組中
                System.arraycopy(cs, 0, newElements, len, cs.length);
                // 寫回内部維護的數組
                setArray(newElements);
            }
            return true;
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.2.35 addAll(int index, Collection<? extends E> c)

/**
     * 将目标數組插入到新數組中 
     */
    public boolean addAll(int index, Collection<? extends E> c) {

        // 将目标參數轉換為數組
        Object[] cs = c.toArray();

        // 加獨占鎖
        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);
            if (cs.length == 0)
                return false;

            // 根據開始添加元素的索引計算需要移動元素個數
            int numMoved = len - index;
            
            // 建立新數組
            Object[] newElements;

            // 如果是數組末尾,則隻是備份舊數組到新數組中,擴充長度
            if (numMoved == 0)
                newElements = Arrays.copyOf(elements, len + cs.length);
            else {
                // 建立新數組,建立新長度
                newElements = new Object[len + cs.length];

                // 将舊數組中index索引之前的元素拷貝到新數組中
                System.arraycopy(elements, 0, newElements, 0, index);
                // 将舊數組中index索引之後的元素拷貝到新數組中插入新元素集合之後的角标之後
                System.arraycopy(elements, index, newElements, index + cs.length, numMoved);
            }
            // 将目标數組插入到新數組中
            System.arraycopy(cs, 0, newElements, index, cs.length);

            // 寫回内部數組
            setArray(newElements);
            return true;
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.2.36 forEach(Consumer<? super E> action)

/**
     * jdk8的lambda方式forEach周遊
     */ 
    public void forEach(Consumer<? super E> action) {
        // 校驗參數
        if (action == null) throw new NullPointerException();

        // 備份數組并擷取長度
        Object[] elements = getArray();
        int len = elements.length;

        // 調用1.8的函數式接口擷取元素
        for (int i = 0; i < len; ++i) {
            @SuppressWarnings("unchecked") E e = (E) elements[i];
            action.accept(e);
        }
    }
           

2.2.37 removeIf(Predicate<? super E> filter)    TODO jdk8

/**
     *
     */
    public boolean removeIf(Predicate<? super E> filter) {
        // 參數校驗
        if (filter == null) throw new NullPointerException();

        // 加獨占鎖
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 備份數組并擷取長度
            Object[] elements = getArray();
            int len = elements.length;

            if (len != 0) {
                int newlen = 0;
                Object[] temp = new Object[len];
                for (int i = 0; i < len; ++i) {
                    @SuppressWarnings("unchecked") E e = (E) elements[i];
                    if (!filter.test(e))
                        temp[newlen++] = e;
                }
                if (newlen != len) {
                    setArray(Arrays.copyOf(temp, newlen));
                    return true;
                }
            }
            return false;
        } finally {
            lock.unlock();
        }
    }
           

2.2.38 replaceAll(UnaryOperator<E> operator) TODO jdk8

public void replaceAll(UnaryOperator<E> operator) {
        if (operator == null) throw new NullPointerException();
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len);
            for (int i = 0; i < len; ++i) {
                @SuppressWarnings("unchecked") E e = (E) elements[i];
                newElements[i] = operator.apply(e);
            }
            setArray(newElements);
        } finally {
            lock.unlock();
        }
    }
           

2.2.39 sort(Comparator<? super E> c)

/**
     * 使用指定的排序器進行排序
     */
    public void sort(Comparator<? super E> c) {
        // 加獨占鎖
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 備份數組
            Object[] elements = getArray();
            // 建立新數組,元素和備份數組一樣 
            Object[] newElements = Arrays.copyOf(elements, elements.length);
            // 調用Arrays的sort方法進行排序
            @SuppressWarnings("unchecked") E[] es = (E[])newElements;
            Arrays.sort(es, c);
            // 寫回
            setArray(newElements);
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.2.40 writeObject(java.io.ObjectOutputStream s)

/**
     * 将數組寫入到指定的輸出流中
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {

        // 寫數組對象資料
        s.defaultWriteObject();
        
        // 備份數組,并将數組的長度寫到流中
        Object[] elements = getArray();
        s.writeInt(elements.length);

        // 将數組元素以合适的順序寫到輸出流中
        for (Object element : elements)
            s.writeObject(element);
    }
           

2.2.41 readObject(java.io.ObjectInputStream s)

/**
     * 從輸入流中擷取數組并寫回
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {

        // 讀對象
        s.defaultReadObject();

        // 擷取新的獨占鎖
        resetLock();

        // 從流中擷取對象數組的長度
        int len = s.readInt();
        // 校驗長度
        SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, len);
        // 建立新數組
        Object[] elements = new Object[len];

        // 從流中擷取對象數組内部的元素
        for (int i = 0; i < len; i++)
            elements[i] = s.readObject();

        // 寫回
        setArray(elements);
    }
           

2.2.42 toString()

/**
     * 重寫toString方法,内部調用Arrays的toString方法
     */
    public String toString() {
        return Arrays.toString(getArray());
    }

    /**
     * Arrays的toString(Arr[])方法,内部采用StringBuilder方法進行拼接
     */
    public static String toString(Object[] a) {
        if (a == null)
            return "null";

        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(String.valueOf(a[i]));
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }
           

2.2.43 equals(Object o)

/**
     * 重寫equals方法
     */
    public boolean equals(Object o) {
        // 如果位址相等,則傳回true
        if (o == this)
            return true;
        // 如果對象不是List類型,則傳回false
        if (!(o instanceof List))
            return false;
        
        // 強轉為List類型并擷取疊代器
        List<?> list = (List<?>)(o);
        Iterator<?> it = list.iterator();

        // 備份内部維護數組并擷取長度
        Object[] elements = getArray();
        int len = elements.length;

        // 周遊目标數組,周遊長度為備份數組的長度
        for (int i = 0; i < len; ++i)
            // 如果二者元素不同則傳回false
            if (!it.hasNext() || !eq(elements[i], it.next()))
                return false;
        // 如果目标數組比備份數組長度長,則傳回false
        if (it.hasNext())
            return false;
        return true;
    }
           

2.2.44 hashCode()

/**
     * 重寫hashCode方法
     */
    public int hashCode() {
        // 初始哈希值為1
        int hashCode = 1;
        // 備份數組并擷取長度
        Object[] elements = getArray();
        int len = elements.length;
        // 周遊元素,根據每一個元素計算一次哈希值
        for (int i = 0; i < len; ++i) {
            Object obj = elements[i];
            // 重新計算哈希值
            hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
        }
        // 傳回新的哈希值
        return hashCode;
    }
           

2.2.45 iterator() 

/**
     * 擷取疊代器,傳回内部自定義類COWIterator的疊代器
     */
    public Iterator<E> iterator() {
        return new COWIterator<E>(getArray(), 0);
    }
           

2.2.46 listIterator()

/**
     * 擷取疊代器,傳回内部自定義類COWIterator的疊代器
     */
    public ListIterator<E> listIterator() {
        return new COWIterator<E>(getArray(), 0);
    }
           

2.2.47 listIterator(int index)

/**
     * 擷取疊代器,傳回内部自定義的COWIterator疊代器,疊代的集合從index索引開始
     */
    public ListIterator<E> listIterator(int index) {
        // 備份數組并擷取長度
        Object[] elements = getArray();
        int len = elements.length;
        // 校驗參數
        if (index < 0 || index > len)
            throw new IndexOutOfBoundsException("Index: "+index);
        // 傳回自定義的疊代器
        return new COWIterator<E>(elements, index);
    }
           

2.2.48 spliterator() TODO jdk8

/**
     *
     */
    public Spliterator<E> spliterator() {
        return Spliterators.spliterator
            (getArray(), Spliterator.IMMUTABLE | Spliterator.ORDERED);
    }
           

2.2.49 subList(int fromIndex, int toIndex)

/**
     * 傳回一個子集合
     */
    public List<E> subList(int fromIndex, int toIndex) {
        // 擷取獨占鎖并加鎖
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 備份數組并擷取長度
            Object[] elements = getArray();
            int len = elements.length;
            // 教研參數
            if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
                throw new IndexOutOfBoundsException();
            // 使用内部類COWSubList建立一個子集合
            return new COWSubList<E>(this, fromIndex, toIndex);
        } finally {
            // 解鎖
            lock.unlock();
        }
    }
           

2.2.50 resetLock()

/**
     * 重置鎖
     */
    private void resetLock() {
        // 使用UNSAFE将lock變量偏移量的位置重置為新的獨占鎖
        UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
    }
           

繼續閱讀