ArrayList源码解读(部分)

Posted Don1911

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList源码解读(部分)相关的知识,希望对你有一定的参考价值。

前言:他山之石,可以攻玉

(1) fastRemove(int i),内部私有方法

    private void fastRemove(int index) {
        //ArrayList内大量使用了此变量,用来验证ArrayList对象结构是否被修改
        modCount++;  
        int numMoved = size - index - 1;    //index后的元素的个数
        if (numMoved > 0)             //0<=index<size-1的情况
        System.arraycopy(elementData, index+1, elementData, index,
                 numMoved);     //ArrayList内大量使用了此方法
        //size减一,且elementData[size(new)]=null方便gc回收空间    
        elementData[--size] = null;   //【包含index为size-1时remove()的情况】  
    }

 

(2) removeAll(c)和retainAll(c)内部的调用方法相同,只有第二个参数不同

    public boolean removeAll(Collection<?> c) {  //删除this和c共有的元素
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }
    public boolean retainAll(Collection<?> c) {  //保留this和c共有的元素
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }
    private boolean batchRemove(Collection<?> c, boolean complement) {  //批量删除
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;  //是否有修改
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement) //complement=true表示保留
                    elementData[w++] = elementData[r];
        } finally {
            if (r != size) {  //若循环中断,则将r及后面的位置的元素复制到w起始的位置
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {  // w!=size 说明数组被修改了
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;    //数组大小变为被保留元素的个数
                modified = true;
            }
        }
        return modified;
    }

 

 (3) subList(int from, int to) 截取List,是通过创建内部类SubList对象实现的

    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);    //界限检查
        return new SubList(this, 0, fromIndex, toIndex);    //0(offset)在内部类SubList没有实际意义 ①
    }
     private class SubList extends AbstractList<E> implements RandomAccess {
        ......
       public E set(int index, E e) {
            rangeCheck(index);    //0<index<size
            checkForComodification();
            E oldValue = ArrayList.this.elementData(offset + index);  //修改的是原ArrayList值  offset=offset(①)+fromIndex
            ArrayList.this.elementData[offset + index] = e;
            return oldValue;    //返回offset+index索引处的old Value
        }
    }

 

(4) iterator() 遍历,通过创建内部类Itr对象实现

    public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {  //采用fail-fast机制
        int cursor;       // 指向数组的下一个元素 (cursor = 下一个元素的索引)
        int lastRet = -1; // 上次返回的元素的索引; 如果不存在上次的返回值,则为-1
        int expectedModCount = modCount; 

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {      //下一个元素 
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1; //再次指向下一个元素
            return (E) elementData[lastRet = i]; //将lastRet指向返回的元素
        }

        public void remove() {  //删除上次next()方法返回的元素
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();
            try {
                ArrayList.this.remove(lastRet);    
                cursor = lastRet;        //将被删除元素的索引赋给cursor
                lastRet = -1;        //next()返回的元素已不存在(被删),则lastRet=-1
                expectedModCount = modCount;    //遍历过程中删除元素不会发生CME异常的原因!
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
        public void forEachRemaining(Consumer<? super E> consumer) { ... }
        ......
    }

 

(5)  listIterator(int i) 与  listIterator(),遍历集合,通过创建内部类ListItr (extends Itr)对象实现,与Itr对比,主要增加了previous()、set()、add()方法

public ListIterator<E> listIterator(int index) {
    if (index < 0 || index > size)        //index=size不报错(可从后往前遍历)
        throw new IndexOutOfBoundsException("Index: "+index);
    return new ListItr(index);
}
public ListIterator<E> listIterator() {
    return new ListItr(0);
}
private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        super();
        cursor = index;
    }

    public boolean hasPrevious() {  //是否存在前一个元素
        return cursor != 0;
    }
    ......public E previous() {
        checkForComodification();
        int i = cursor - 1;
        if (i < 0)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i;                //指向下一个元素的cursor也对应向前移动
        return (E) elementData[lastRet = i];    //lastRet指向返回的元素
    }

    public void set(E e) { //改变元素的值,相当于arrayList.set(lastRet,e);
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.set(lastRet, e);    //modCount不会改变
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    public void add(E e) {
        checkForComodification();
        try {
            int i = cursor;
            ArrayList.this.add(i, e);
            cursor = i + 1;
            lastRet = -1;
            expectedModCount = modCount; //重新赋值给expectedModCount
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}

 

(6) spliterator() 可分割迭代器,是Java为了并行遍历数据源中的元素而设计的 通过创建内部类ArrayListSpliterator对象实现 

    public Spliterator<E> spliterator() {
        return new ArrayListSpliterator<>(this, 0, -1, 0);
    }

    /* 基于索引分割,懒初始化 */
    static final class ArrayListSpliterator<E> implements Spliterator<E> {
        private final ArrayList<E> list;
        private int index; // 当前元素索引, 调用advance/split时定义其初始值
        private int fence; // 使用前为-1; 调用时为size值
        private int expectedModCount; // initialized when fence set

        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,        //new ArrayListSpliterator<>(this, 0, -1, 0);
                             int expectedModCount) {
            this.list = list;    // 不遍历时list可为null
            this.index = origin;    //起始索引
            this.fence = fence;        //边界
            this.expectedModCount = expectedModCount;
        }

        private int getFence() { // 首次使用时将fence初始化为size值
            int hi; // 一个出现在forEach()中特殊的变量
            ArrayList<E> lst;
            if ((hi = fence) < 0) {
                if ((lst = list) == null)
                    hi = fence = 0;
                else {
                    expectedModCount = lst.modCount;
                    hi = fence = lst.size;
                }
            }
            return hi;
        }

        public ArrayListSpliterator<E> trySplit() {        //分割
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null : // 除非元素太少(0或1),否则从中间(mid)分割
                new ArrayListSpliterator<E>(list, lo, index = mid,    //父spliterator的index变为mid
                                            expectedModCount);        //即分割后,父spliterator[mid,size-1]
                                                                    //子spliterator[index, mid-1]
        }

        public boolean tryAdvance(Consumer<? super E> action) {    //对index索引处的元素进行操作
            if (action == null)
                throw new NullPointerException();
            int hi = getFence(), i = index;    //
            if (i < hi) {    //若spliterator元素不为空
                index = i + 1;     //index索引+1
                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
                action.accept(e);    //对index(②)处的元素进行操作,可能改变原数组的元素
                if (list.modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                return true;
            }
            return false;
        }

        public void forEachRemaining(Consumer<? super E> action) {
            int i, hi, mc; // hoist accesses and checks from loop
            ArrayList<E> lst; Object[] a;
            if (action == null)
                throw new NullPointerException();
            if ((lst = list) != null && (a = lst.elementData) != null) {
                if ((hi = fence) < 0) {    //若fence未初始化,即未曾调用trySplite()或tryAdvance(Consumer c)
                    mc = lst.modCount;
                    hi = lst.size;
                }
                else
                    mc = expectedModCount;
                if ((i = index) >= 0 && (index = hi) <= a.length) {
                    for (; i < hi; ++i) {
                        @SuppressWarnings("unchecked") E e = (E) a[i];
                        action.accept(e);    //操作index至hence-1的元素
                    }
                    if (lst.modCount == mc)        
                        return;
                }
            }
            throw new ConcurrentModificationException();
        }

        public long estimateSize() {    //返回listerator大小
            return (long) (getFence() - index);
        }

        public int characteristics() {    //返回特征值(不同值相或后的结果不相等,所以可通过该值辨识出有什么特征)
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
        }
    }

其它方法相对上面方法易懂

以上是关于ArrayList源码解读(部分)的主要内容,如果未能解决你的问题,请参考以下文章

ArrayList源码解读

ArrayList扩容源码详细解读(JDK1.8)

Java源码解读系列:ArrayList

ArrayList 源码解读

源码阅读Java集合 - ArrayList深度源码解读

源码解读:ArrayList源码解析(JDK8)