源码分析一:ArrayList

一、如何分析

    第一次做源码分析,借鉴网上的分析方法,做一次尝试

1)找到ArrayList类,获得源码

2)创建自己的类:ArrayList和AbstractList类

3)编写测试样例,断点调试,分析ArrayList的运行细节

二、源码分析

1、变量

  /**
   * 默认容量
   */
  private static final int DEFAULT_CAPACITY = 10;

  /**
   * 空数组实例
* 当用户指定该 ArrayList 容量为 0 时,返回该空数组
   */
  private static final Object[] EMPTY_ELEMENTDATA = {};

  /**
   * 空数组实例
   * 无参构造器返回该空数组实例
   */
  private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

  /**
   * 缓存数组变量
   * 若该数组初始化为DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组实例
   * 在首次添加元素时,扩容成默认容量DEFAULT_CAPACITY=10
   */
  transient Object[] elementData; // non-private to simplify nested class access

  /**
   * 数组实际元素个数
   */
  private int size;
/**
 * 最大可分配的数组空间大小为Integer最大值-8
 * OutOfMemoryError: 达到数组最大长度会内存溢出
 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

2、构造函数

/**
 * 构造函数
 * 根据提供的初始容量大小,创建一个空的数组对象
 * @param  initialCapacity  容器的初始容量
 * @throws IllegalArgumentException 初始容量必须大于等于0,否则抛出该异常
 */
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+ 
                                           initialCapacity);
    }
}
/**
 * 无参构造器
 * 缓冲数组赋值为空数组
 * 首次添加时,初始化为默认容量
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

/**
 * 构建一个包含Collection集合的数组
 *
 * @param c 包含数组元素的集合(实现Collection接口的集合)
 * @throws NullPointerException 如果指定的集合为空,抛出空指针异常
 */
public ArrayList(Collection<? extends E> c) {
    // 转化指定的集合为Object数组,并赋值给当前数组
    elementData = c.toArray();
    // 数组长度赋值给size,并判断是否为0
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        // 判断当前缓冲数组是不是Object数组类型
        if (elementData.getClass() != Object[].class)
            // 如果c.toArray返回的不是Object[],重新构造一个大小为size的Object[],赋值给缓冲数组
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        // 如果数组大小为0,返回空数组
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

3、方法

/**
 * 减少数组所占的空间大小,缩减为当前size的大小,减少空间的消费
 * 手动减少空间占用
 * 空间自动扩容造成的资源浪费
 */
public void trimToSize() {
    // AbstractList内protected变量,
    // 猜测:应该与并发安全的list有关,CAS,用来判断当前List是否并发被修改,与Arraylist没关系
    modCount++;
    // 判断当前数组元素的实际个数是否小于分配的空间个数
    if (size < elementData.length) {
        // 判断实际个数是否为0
        // 0:缓冲数组大小为0
        // 不为0:缓冲数组大小为实际元素个数
        elementData = (size == 0)
          ? EMPTY_ELEMENTDATA
          : Arrays.copyOf(elementData, size);
    }
}
/**
 * 数组扩容,确保缓冲数组至少包含指定的容量
 * 提供给用户使用,本类未使用
 * @param   minCapacity   用户指定的最小容量
 */
public void ensureCapacity(int minCapacity) {
    // 判断缓冲数组是否为空数组
    // 不为空:不需要扩容,最小扩容为0
    // 为空:扩容大小为默认容量
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        // any size if not default element table
        ? 0
        // larger than default for default empty table. It's already
        // supposed to be at default size.
        : DEFAULT_CAPACITY;
    // 判断用户指定最小容量是否大于最小扩容
    if (minCapacity > minExpand) {
        // 若用户指定的最小容量大于最小扩容,以用户指定的容量来扩容
        ensureExplicitCapacity(minCapacity);
    }
}

// 明确数组的最小容量,提供给本类使用
private void ensureExplicitCapacity(int minCapacity) {
    // 并发操作
    modCount++;
    // overflow-conscious code
    // ?? 防止溢出代码:确保指定的最小容量 > 缓冲数组当前的长度
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// 明确数组的最小容量,提供给本类使用
// minCapacity :指定的最小容量
private void ensureCapacityInternal(int minCapacity) {
    // 若缓冲数组为空,最小扩容为默认容量和参数容量之间的最大值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}



/**
 * 最大可分配的数组空间大小为Integer最大值-8
 * 减8的原因:一些虚拟机会在数组中存储某些数据
 * OutOfMemoryError: 达到数组最大长度会内存溢出
 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

/**
 * 扩容数组缓冲,以保证其至少包含指定容量的参数空间
 *
 * @param minCapacity 指定的最小容量
 */
private void grow(int minCapacity) {
    // overflow-conscious code
    // 缓冲数组当前容量
    int oldCapacity = elementData.length;
    // 新容量为 原容量 + 原容量/2
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        // 如果新容量小于指定的最小容量,指定新容量为指定容量
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        // 新容量大于最大可分配的容量,则进行大容量分配
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    // 原数组copy到新容量大小的对象数组中,赋值给缓冲数组
    elementData = Arrays.copyOf(elementData, newCapacity);
}

// 大容量分配,需要分配的容量大于Integer.Max_value-8,最大分配Integer.MAX_VALUE
private static int hugeCapacity(int minCapacity) {
    // 如果指定的最小容量小于0,则是内存溢出
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    // 指定最小容量大于Integer最大值-8,返回Integer最大值,否则返回Integer最大值-8
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}
/**
 * 返回数组实际的元素个数
 *
 * @return 元素个数
 */
public int size() {
    return size;
}

/**
 * 是否为空数组
 *
 */
public boolean isEmpty() {
    return size == 0;
}

/**
 * 是否包含指定元素
 * 至少包含一个指定元素
 * @param o 指定元素
 * @return 包含:true;不包含:false;
 */
public boolean contains(Object o) {
    // 根据Index是否大于等于0,来判断时候包含
    return indexOf(o) >= 0;
}

/**
 * 返回该数组中第一次出现该元素的位置索引
 * 不存在该元素:返回-1
 * 顺序遍历缓冲数组,可以存储null,所以null和非null分开遍历
 */
public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

/**
 * 返回该数组中最后一次出现该元素的位置索引
 * 不存在该元素:返回-1
 * 逆序遍历缓冲数组,可以存储null,所以null和非null分开遍历
 */
public int lastIndexOf(Object o) {
    if (o == null) {
        for (int i = size-1; i >= 0; i--)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = size-1; i >= 0; i--)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}
/**
 * 当前ArrayList的浅复制
 * 当前类实现Cloneable接口,拷贝ArrayList
 * 安全性:
 * 1)新增、删除元素不会影响原来的ArrayList
 * 2)拷贝的数组元素引用对象的修改会影响原来的ArrayList
 * @return a clone of this <tt>ArrayList</tt> instance
 */
public Object clone() {
    try {
        // Object对象的clone方法,拷贝ArrayList内的基本数据类型和String,不会复制引用对象
        ArrayList<?> v = (ArrayList<?>) super.clone();
        // 缓冲数组赋值一份到新的ArrayList中,对象的引用复制,修改会影响原数组的对象
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

/**
 * 返回ArrayList的Object数组
 * 原理:拷贝一份缓冲数组的元素到新的数组,元素顺序和当前缓冲数组一致
 * 安全性:
 * 1)新增、删除元素不会影响原来的ArrayList
 * 2)拷贝的数组元素引用对象的修改会影响原来的ArrayList
 */
public Object[] toArray() {
    return Arrays.copyOf(elementData, size);
}
/**
 * 用指定的数组来存储ArrayList中的所有元素
 *
 * @param a 需要存储当前数组元素的数组
 * @return 返回包含当前数组元素的对象数组
 * @throws ArrayStoreException 如果运行时类型不是当前ArrayList中存储的元素的基类,报错
 * @throws NullPointerException 指定类型的数组为空时,空指针
 */
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
         // 指定的数组空间小于当前ArrayList的元素大小,创建一个指定数组类型的新数组
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    // 否则,拷贝当前缓冲数组的元素到指定数组,索引从0开始
    System.arraycopy(elementData, 0, a, 0, size);
    // 如果指定数组空间大于当前ArrayList的元素个数,设置第size + 1个元素为null
    if (a.length > size)
        a[size] = null;
    return a;
}
/**
 * 根据索引获得元素,内部方法
 * @param index
 * @return
 */
@SuppressWarnings("unchecked")
E elementData(int index) {
    return (E) elementData[index];
}
/**
 * 检查提供的索引是否大于等于当前元素个数
 */
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
 * 指定位置插入元素
 * 判断角标是否越界:
 *  支持0-size位置插入元素
 */
private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

/**
 * 根据索引获得元素,索引从0开始
 *
 * @param  index 元素的索引
 * @throws IndexOutOfBoundsException 数组越界异常
 */
public E get(int index) {
    // 检查数组越界
    rangeCheck(index);

    return elementData(index);
}
/**
 * 替换指定位置的元素为指定元素
 */
public E set(int index, E element) {
    // 检查索引是否越界
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    // 返回被替换的元素
    return oldValue;
}

/**
 * 在数组尾部添加指定的元素
 */
public boolean add(E e) {
    // 调用内部扩容方法,确保数组空间足够,如果size + 1 大于缓冲数组的空间,进行数组的拷贝,扩容为原来的1.5倍
    // 如果还是小于size + 1,那么就构建一个size + 1大小的数组
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

/**
 * 在ArrayList指定位置加入指定元素,index支持0-size
 *
 */
public void add(int index, E element) {
    // 判断角标是否越界
    rangeCheckForAdd(index);
    // 调用内部扩容方法,判断是否需要扩容
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    // 将插入位置后的所有的元素后移一位
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}
/**
 * 删除指定位置的元素
 */
public E remove(int index) {
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);
    // 需要移动的元素个数
    int numMoved = size - index - 1;
    // 将index后的所有数据全部左移一位
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}
/**
 * 删除第一个符合要求的元素
 * 顺序查找,从0开始,删除第一个出现的元素
 * null特殊处理
 */
public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                // 调用内部快速删除方法
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

/*
 * 快速删除第Index元素
 * 私有方法,不经过检查,不返回被删除的元素
 */
private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}

/**
 * 移除list中的所有元素,这个list表将在调用之后置空
 * 缓冲数组中的所有元素置为:null
 * 清空后:toString和迭代器处理为[]
 */
public void clear() {
    modCount++;

    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

/**
     * 追加指定的集合到该ArrayList的后部
     * 该方法是不安全的,如果指定的集合被其他线程修改,那么加入到该Arraylist可能会有问题
     *
     * @param c 指定要追加的集合
     * @return true or false
     * @throws NullPointerException 指定集合为空
     */
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        // 确保当前缓冲数组容量足够支持
        ensureCapacityInternal(size + numNew);  // Increments modCount
        // 从当前数组有效元素最后的角标开始复制指定集合的元素
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    /**
     * 从指定位置插入指定集合的所有元素
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        // 角标越界检查,0<= index <=size
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        // 从指定位置,计算需要移动的元素个数
        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

    /**
     *  删除指定位置之间的所有元素
     *
     * @throws IndexOutOfBoundsException if {@code fromIndex} or
     *         {@code toIndex} is out of range
     *         ({@code fromIndex < 0 ||
     *          fromIndex >= size() ||
     *          toIndex > size() ||
     *          toIndex < fromIndex})
     */
    protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        // 计算需要移动的元素个数
        int numMoved = size - toIndex;
        // 将指定结束位置之后的所有元素copy到从开始位置开始的空间
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        // 修改当前实际集合的元素个数
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            // 置空新元素个数角标后的所有元素,由垃圾收集器处理
            elementData[i] = null;
        }
        size = newSize;
    }

    /**
     * 检查提供的索引是否大于等于当前元素个数
     */
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * 指定位置插入元素
     * 判断角标是否越界:
     *  支持0-size位置插入元素
     */
    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * 构造IndexOutOfBoundsException详细信息
     */
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

    /**
     * 删除元素(元素在指定元素集合里)
     *
     * @param c 指定需要删除元素的集合
     */
    public boolean removeAll(Collection<?> c) {
        // 指定集合空判断
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

    /**
     * 删除元素(元素不在指定元素集合里)
     *
     * @param c 指定不需要删除的元素集合
     * @throws ClassCastException 当前集合的元素和指定集合内的元素不匹配
     */
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

    // 批量删除方法,私有方法,供本类使用
    // Collection :指定集合;
    // complement: 是否删除标志位
    //      true-保留;false:删除;
    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++)
                // !!首先判断指定集合是否包含该元素
                // 根据complement确定需要保留的元素,将保留的元素放入数组前段位置
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            // 如果r最后不等于size,那么就是出了异常了
            if (r != size) {
                // 保留还没有遍历到的元素
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                // 更新要保留的元素个数
                w += size - r;
            }
            // 如果要保留的元素个数不是全部
            if (w != size) {
                // clear to let GC do its work
                // 将缓冲数组中要保留个数后面的所有元素全部置空,由GC处理
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                // 修改的元素个数
                modCount += size - w;
                size = w;
                // 修改成功标志位
                modified = true;
            }
        }
        return modified;
    }

    /**
     * 私有方法
     * 序列化ArrayList
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // Write out element count, and any hidden stuff
        // 当前修改次数
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioural compatibility with clone()
        // 写入元素个数
        s.writeInt(size);

        // Write out all elements in the proper order.
        // 按缓冲数组顺序写入
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }
        // fail-fast:如果在序列化时有其他线程修改了数组,抛出异常
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

    /**
     * 私有方法,反序列化重构ArrayList实例
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // 初始化数组为空
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        // 读取元素个数和隐藏信息
        s.defaultReadObject();

        // Read in capacity
        // 读取容量
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            // 类似克隆,根据实际大小分配空间,而不是根据容量来分配
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }

    /**
     * 返回指定元素角标开始的所有元素迭代器
     */
    public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }

    /**
     * 返回角标从0开始的元素迭代器
     */
    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }

    /**
     * 返回合适排序的元素迭代器
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

/**
     * JDK 8 新方法:将元素交由Consumer来遍历
     * @param action
     */
    @Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

 // 根据条件过滤删除元素
    @Override
    public boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        // figure out which elements are to be removed
        // any exception thrown from the filter predicate at this stage
        // will leave the collection unmodified
        int removeCount = 0;
        final BitSet removeSet = new BitSet(size);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            @SuppressWarnings("unchecked")
            final E element = (E) elementData[i];
            if (filter.test(element)) {
                removeSet.set(i);
                removeCount++;
            }
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }

        // shift surviving elements left over the spaces left by removed elements
        final boolean anyToRemove = removeCount > 0;
        if (anyToRemove) {
            final int newSize = size - removeCount;
            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            for (int k=newSize; k < size; k++) {
                elementData[k] = null;  // Let gc do its work
            }
            this.size = newSize;
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }

        return anyToRemove;
    }

/*
    * UnaryOperator 接受一个什么类型的参数,返回一个什么类型的参数
    * 对数组中的每一个元素进行一系列的操作,返回同样类型的元素,
    *
    * 接收当前位置的元素,处理完后,返回给List
    * */
    @Override
    @SuppressWarnings("unchecked")
    public void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            elementData[i] = operator.apply((E) elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

// 排序
    @Override
    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

 4.内部类

扫描二维码关注公众号,回复: 3676967 查看本文章

1)内部迭代器

/**
 * 内部类
 * AbstractList.Itr 的优化版本
 * 建立一个指向原来对象的单链索引表,在原来对象被修改时,索引表不会被修改,
 * 遍历就会基于fail-fast,直接抛出java.util.ConcurrentModificationException 异常
 */
private class Itr implements Iterator<E> {
    // 下一个元素的游标
    int cursor;       // index of next element to return
    // 遍历到最后一个元素的标志位
    int lastRet = -1; // index of last element returned; -1 if no such
    // fail-fast:遍历期间,修改ArrayList直接抛出异常
    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];
    }

    // 删除元素
    // 通过此方法,可以在遍历时删除元素
    // 通过ArrayList.remove方法删除元素会抛出异常
    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            // 当前游标位置后的所有元素左移一位
            ArrayList.this.remove(lastRet);
            // 游标重置到当前位置
            cursor = lastRet;
            // 将最后一个元素返回的索引重置为-1
            lastRet = -1;
            //重新设置了expectedModCount的值,避免了ConcurrentModificationException的产生
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    
/**
 * JDK8 中新方法
 * 迭代器遍历List中所有元素
 * 通过Consumer函数式接口遍历
 *
 * 注意:
 *  遍历过程中,不可修改ArrayList的元素
 * @param consumer
 */
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
    Objects.requireNonNull(consumer);
    // 获取到实际数组元素个数
    final int size = ArrayList.this.size;
    // 获取到当前游标位置
    int i = cursor;
    // 若游标已至最后一位,返回空
    if (i >= size) {
        return;
    }
    // copy 一份当前ArrayList的缓冲数组
    final Object[] elementData = ArrayList.this.elementData;
    if (i >= elementData.length) {
        throw new ConcurrentModificationException();
    }
    // 循环接收数组元素,且modCount在遍历过程中不可修改
    while (i != size && modCount == expectedModCount) {
        // 以consumer 来接收所有的元素
        consumer.accept((E) elementData[i++]);
    }
    // update once at end of iteration to reduce heap write traffic
    cursor = i;
    // 结束位
    lastRet = i - 1;
    // 检查是否被修改
    checkForComodification();
}

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

2)ArrayList 优化版迭代器

/**
 * AbstractList.ListItr 的优化版本
 * 在Itr的基础上,增加了向前移动的遍历
 */
private class ListItr extends Itr implements ListIterator<E> {
    // 构造函数,可以从指定位置开始遍历,实际上是将游标位置指向指定的位置
    ListItr(int index) {
        super();
        cursor = index;
    }
    // 是否有前置元素,实际上是判断元素是否是第一个
    public boolean hasPrevious() {
        return cursor != 0;
    }
    // 返回当前角标位置
    public int nextIndex() {
        return cursor;
    }
    // 返回前置元素角标,先判断是否有前置元素
    public int previousIndex() {
        return cursor - 1;
    }

    // 获取前一个元素,当前角标-1
    @SuppressWarnings("unchecked")
    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;
        // 返回当前遍历的元素
        return (E) elementData[lastRet = i];
    }

    // 重置当前角标的元素
    public void set(E e) {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.set(lastRet, e);
        } 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;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}

3)内部类 SubList 截取的子类

/**
 * 获取缓冲数组 从开始角标到结束角标的元素[) 左闭右开
 * 实际上对子类的操作,都是对父类的操作,此时不能再对父类修改
 * 返回内部类对象
 * 1.子集修改会影响父集
 * 2.父集删除、新增,子类抛出ConcurrentModificationException异常
 *  所以这时得用子类的方法去新增、删除元素
 */
public List<E> subList(int fromIndex, int toIndex) {
    subListRangeCheck(fromIndex, toIndex, size);
    return new SubList(this, 0, fromIndex, toIndex);
}

// 角标参数核查
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
    if (fromIndex < 0)
        throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
    if (toIndex > size)
        throw new IndexOutOfBoundsException("toIndex = " + toIndex);
    if (fromIndex > toIndex)
        throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                           ") > toIndex(" + toIndex + ")");
}

// 内部类 子集 实现随机访问
private class SubList extends AbstractList<E> implements RandomAccess {
    // 父集引用
    private final AbstractList<E> parent;
    // 父集的偏移量 即fromIndex
    private final int parentOffset;
    // 偏移量
    private final int offset;
    int size;

    SubList(AbstractList<E> parent,
            int offset, int fromIndex, int toIndex) {
        // 指向父集:子类其实是指向父集的一部分区间,所以子集修改会影响父集
        this.parent = parent;
        // 父集的偏移量,等同于开始角标
        this.parentOffset = fromIndex;
        // 偏移量,默认为0,不进行偏移
        this.offset = offset + fromIndex;
        // 元素实际个数
        this.size = toIndex - fromIndex;
        // 父集的修改次数
        this.modCount = ArrayList.this.modCount;
    }

    // 在指定位置设置指定的值,返回旧值
    public E set(int index, E e) {
        rangeCheck(index);
        checkForComodification();
        // 是在父集上修改
        E oldValue = ArrayList.this.elementData(offset + index);
        ArrayList.this.elementData[offset + index] = e;
        return oldValue;
    }

    // 获取指定索引的元素
    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        return ArrayList.this.elementData(offset + index);
    }

    // 返回元素的数量
    public int size() {
        checkForComodification();
        return this.size;
    }

    // 指定位置添加元素
    public void add(int index, E e) {
        rangeCheckForAdd(index);
        checkForComodification();
        // 实质上是父集的增加,子集指向父集的一段
        parent.add(parentOffset + index, e);
        // 将父集修改同步到子类中
        this.modCount = parent.modCount;
        this.size++;
    }

    // 移除指定位置的元素
    public E remove(int index) {
        rangeCheck(index);
        checkForComodification();
        E result = parent.remove(parentOffset + index);
        this.modCount = parent.modCount;
        this.size--;
        return result;
    }

    // 移除subList中的[fromIndex,toIndex)之间的元素
    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        parent.removeRange(parentOffset + fromIndex,
                           parentOffset + toIndex);
        this.modCount = parent.modCount;
        this.size -= toIndex - fromIndex;
    }
    // 添加集合中的元素到subList结尾
    public boolean addAll(Collection<? extends E> c) {
        // 调用父集的方法添加集合元素
        return addAll(this.size, c);
    }

    // 在subList指定位置,添加集合中的元素
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        int cSize = c.size();
        if (cSize==0)
            return false;

        checkForComodification();
        //父集的方法添加
        parent.addAll(parentOffset + index, c);
        this.modCount = parent.modCount;
        this.size += cSize;
        return true;
    }

    // subList中的迭代器
    public Iterator<E> iterator() {
        return listIterator();
    }

    // 返回从指定索引开始到结束的元素的list双向迭代器
    // 与ArrayList 方法类似
    public ListIterator<E> listIterator(final int index) {
        checkForComodification();
        rangeCheckForAdd(index);
        final int offset = this.offset;

        return new ListIterator<E>() {
            int cursor = index;
            int lastRet = -1;
            int expectedModCount = ArrayList.this.modCount;

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

            @SuppressWarnings("unchecked")
            public E next() {
                checkForComodification();
                int i = cursor;
                if (i >= SubList.this.size)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (offset + i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[offset + (lastRet = i)];
            }

            public boolean hasPrevious() {
                return cursor != 0;
            }

            @SuppressWarnings("unchecked")
            public E previous() {
                checkForComodification();
                int i = cursor - 1;
                if (i < 0)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (offset + i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i;
                return (E) elementData[offset + (lastRet = i)];
            }

            @SuppressWarnings("unchecked")
            public void forEachRemaining(Consumer<? super E> consumer) {
                Objects.requireNonNull(consumer);
                final int size = SubList.this.size;
                int i = cursor;
                if (i >= size) {
                    return;
                }
                final Object[] elementData = ArrayList.this.elementData;
                if (offset + i >= elementData.length) {
                    throw new ConcurrentModificationException();
                }
                while (i != size && modCount == expectedModCount) {
                    consumer.accept((E) elementData[offset + (i++)]);
                }
                // update once at end of iteration to reduce heap write traffic
                lastRet = cursor = i;
                checkForComodification();
            }

            public int nextIndex() {
                return cursor;
            }

            public int previousIndex() {
                return cursor - 1;
            }

            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();

                try {
                    SubList.this.remove(lastRet);
                    cursor = lastRet;
                    lastRet = -1;
                    expectedModCount = ArrayList.this.modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }

            public void set(E e) {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();

                try {
                    ArrayList.this.set(offset + lastRet, e);
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }

            public void add(E e) {
                checkForComodification();

                try {
                    int i = cursor;
                    SubList.this.add(i, e);
                    cursor = i + 1;
                    lastRet = -1;
                    expectedModCount = ArrayList.this.modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }

            final void checkForComodification() {
                if (expectedModCount != ArrayList.this.modCount)
                    throw new ConcurrentModificationException();
            }
        };
    }

    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, offset, fromIndex, toIndex);
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= this.size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > this.size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+this.size;
    }

    private void checkForComodification() {
        if (ArrayList.this.modCount != this.modCount)
            throw new ConcurrentModificationException();
    }

    public Spliterator<E> spliterator() {
        checkForComodification();
        return new ArrayListSpliterator<E>(ArrayList.this, offset,
                                           offset + this.size, this.modCount);
    }
}

4)分割器

/**
 * 获取分割器
 * 1.fail-fast机制:快速失败
 * 2.late-binding:后期绑定
 * @since 1.8
 */
@Override
public Spliterator<E> spliterator() {
    return new ArrayListSpliterator<>(this, 0, -1, 0);
}

/** Index-based split-by-two, lazily initialized Spliterator */
// 基于索引、二分、懒加载的分割器
static final class ArrayListSpliterator<E> implements Spliterator<E> {
    // 存放ArrayList对象
    private final ArrayList<E> list;
    // 当前位置
    private int index; // current index, modified on advance/split
    // 结束位置,默认为-1
    private int fence; // -1 until used; then one past last index
    // 期待的修改值
    private int expectedModCount; // initialized when fence set

    /** Create new spliterator covering the given  range */
    ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                         int expectedModCount) {
        this.list = list; // OK if null unless traversed
        this.index = origin;
        this.fence = fence;
        this.expectedModCount = expectedModCount;
    }

    //在第一次使用时实例化结束位置
    private int getFence() { // initialize fence to size on first use
        int hi; // (a specialized variant appears in method forEach)
        ArrayList<E> lst;
        // 第一次结束位置为-1
        if ((hi = fence) < 0) {
            if ((lst = list) == null)
                hi = fence = 0;
            else {
                // 修改值为实际修改值
                expectedModCount = lst.modCount;
                // 初始化结束位置为实际元素个数,
                hi = fence = lst.size;
            }
        }
        return hi;
    }

    /*
    * 分割list,返回一个新的分割器实例
    * 二分法
    *
    * */
    public ArrayListSpliterator<E> trySplit() {
        // hi:高位;lo:低位;mid:中间位置索引
        int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
        // 如果低位小于中间位置索引,返回以低位开始,中间位置为结束的分割器
        return (lo >= mid) ? null : // divide range in half unless too small
            new ArrayListSpliterator<E>(list, lo, index = mid,
                                        expectedModCount);
    }
    // 是否还有元素可以遍历
    public boolean tryAdvance(Consumer<? super E> action) {
        if (action == null)
            throw new NullPointerException();
        int hi = getFence(), i = index;
        if (i < hi) {
            index = i + 1;
            @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
            action.accept(e);
            // 父集合期间不允许修改
            if (list.modCount != expectedModCount)
                throw new ConcurrentModificationException();
            return true;
        }
        return false;
    }

    // 通过Consumer Action遍历所有的分割器元素
    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) {
                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);
                }
                if (lst.modCount == mc)
                    return;
            }
        }
        throw new ConcurrentModificationException();
    }

    // 估计分割器中实际元素个数
    public long estimateSize() {
        return (long) (getFence() - index);
    }

    // ? : 不知道什么用?
    public int characteristics() {
        return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
    }
}

猜你喜欢

转载自blog.csdn.net/stubborn_ugly/article/details/81740123