其他分享
首页 > 其他分享> > Collection之ArrayList

Collection之ArrayList

作者:互联网

对于通过数组来维护数据的集合来说,并不是新增一个数据就进行一次数组长度的扩充。而是按照指定规则一次性扩充一定长度。这个数组称为数据缓存区,她的长度为容量,

ArrayList:Collection下List的一员,通过维护一个数组来实现,这个数组便为这个ArrayList的数据缓存区,它的长度即为这个List的容量(capacity)。

容量(capacity)与大小(size)是不同的概念:对于通过数组来维护数据的集合来说,数组便是集合的容器,并不是新增一个数据就进行一次容量(数组长度)的扩充。而是按照指定规则(数据量达到一定程度,不同集合的扩充的时间有些许差异)一次性扩充一定(不同集合的每次扩充的量有些许差异)长度。size表示容器中存放数据的数量,容量capacity是指容器的大小(数组长度)。

/**-------------继承自父类AbstractList------Start------------*/
/**
 * - 记录这个List被修改的次数。主要用于迭代过程中的检查当前集合是否已被改变。
 * - 如果迭代过程中发现这个值被改变,就会依据fail fast原则抛出concurrentModificationException异常。
 * - 至于List的何种改变会引起modCount的改变则由继承了AbstractList的类去自行决定。
 * - 如有必要甚至可以在任何时间都不引起modCount的改变,这样在对List的迭代过程中就永远不会抛出 
 *   concurrentModificationException异常。
 *   但是这样会导致List的数据在迭代过程中发生改变。失去数据在迭代过程中的一致性
 */
protected transient int modCount = 0;
/**-------------继承自父类AbstractList------End------------*/

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

/**
 * - 一个空的数据缓冲区
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
 * - 一个默认容量(DEFAULT_CAPACITY)的数据缓冲区.
 *   它的长度是0,它本身并不是默认容量(DEFAULT_CAPACITY)的数据缓冲区。
 *   只是标识着需要建一个默认容量的数据缓冲区,真正的默认容量的数据缓冲区会在List第一次进行Add时 
 *   创建
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
 * - 数据缓存区,他的长度就是ArrayList的容量.
 *   无论这个List的成员元素是什么类型,都会被放到Object[]的数组而不是E[]的数组里面
 */
transient Object[] elementData; // non-private to simplify nested class access

/**
 * The size of the ArrayList (the number of elements it contains).
 * - List的大小(数据量)
 */
private int size;
/**
 * - 所能允许设置的最大数据缓存区大小,任何大于这个值的缓存区设置都会被重置为Integer.MAX_VALUE(不会-8)
 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
 * 	-构造一个指定容量的List,容量需要大于0,等于0直接赋值EMPTY_ELEMENTDATA,小于0抛出异常IllegalArgumentException
 */
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);
	}
}

/**
 * 	- 构造一个默认容量(10)的List,注意长度为10的数据缓存区并不是在这里就创建了,而是在第一次add的
 *    时间,DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个长度为0的空数组,他只是标识着要建立一个默认
 *    的数据缓冲区
 */
public ArrayList() {
	this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

/**
 * - 构造一个带有初始值的List.其容量为初始集合的大小.无论是何种类型的初始集合,
 *	 都会被转为Object[]数组存储
 */
public ArrayList(Collection<? extends E> c) {
	elementData = c.toArray();
	if ((size = elementData.length) != 0) {
		// c.toArray might (incorrectly) not return Object[] (see 6260652)
		if (elementData.getClass() != Object[].class)
			elementData = Arrays.copyOf(elementData, size, Object[].class);
	} else {
		// replace with empty array.
		this.elementData = EMPTY_ELEMENTDATA;
	}
}
  1. ArrayList的整体操作

    /**
     * - 调整缓冲区大小。由于数据缓存的扩充规则,数据缓存区的大小都是大于等于List中实际存入的数据量的。
     * - 这个方法就是将数据缓存区的大小调整为和List的实际数据量一致。释放申请出来的未使用数据缓存区
     */
    public void trimToSize() {
    	// modCount增加标记ArrayList发生改变
    	modCount++;
    	// - 如果缓冲区大小比数据量大-数据量为0时直接赋值缓冲区EMPTY_ELEMENTDATA,
    	//   否则按照数据量创建一个新的数组作为数据缓冲区,老的数据缓冲区会被GC掉
    	if (size < elementData.length) {
    		elementData = (size == 0)
    		  ? EMPTY_ELEMENTDATA
    		  : Arrays.copyOf(elementData, size);
    	}
    }
    
    
     /**
     * - 确保缓冲区的大小大于指定值,如果List本身是采用默认长度进行缓冲区创建,
     *   且尚未进行实际缓冲区创建时,那么无法指定比默认缓冲区长度更小的值
     */
    public void ensureCapacity(int minCapacity) {
    	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);
    	}
    }
    // - 同ensureCapacity,不过是私有的,且不要求指定缓冲区大小要比当前缓冲区大小大
    private void ensureCapacityInternal(int minCapacity) {
    	if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    		minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    	}
    
    	ensureExplicitCapacity(minCapacity);
    }
    // 容量扩充预操作
    private void ensureExplicitCapacity(int minCapacity) {
    	// modCount增加标记ArrayList发生改变
    	modCount++;
    	// overflow-conscious code
        // 要保证缓冲区大小比数据量大
    	if (minCapacity - elementData.length > 0)
    		grow(minCapacity);
    }
    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     * - 进行容量扩充
     */
    private void grow(int minCapacity) {
    	// overflow-conscious code
    	// 原数据缓冲区大小
    	int oldCapacity = elementData.length;
    	// 在原数据缓冲区大小的基础上扩充原大小的1/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: 
    	// 按照新的缓冲区容量创建新的缓冲区
    	elementData = Arrays.copyOf(elementData, newCapacity);
    }
    // 小于0抛异常,大于MAX_ARRAY_SIZE重置为Integer.MAX_VALUE(因为这里入参是int所以最大值也就是
    //    Integer.MAX_VALUE,如果通过运算实际结果获得比Integer.MAX_VALUE大那么根据int的溢出原则就 
    //    会得到小于0的值,进入小于0的流程抛出异常)
    private static int hugeCapacity(int minCapacity) {
    	if (minCapacity < 0) // overflow
    		throw new OutOfMemoryError();
    	return (minCapacity > MAX_ARRAY_SIZE) ?
    		Integer.MAX_VALUE :
    		MAX_ARRAY_SIZE;
    }
    
    /**
     * - List中当前的数据量大小
     */
    public int size() {
    	return size;
    }
    
     /**
     * - List当前数据量是否为0(为空)
     */
    public boolean isEmpty() {
    	return size == 0;
    }
    
    /**
     * - 克隆一个当前List的实例
     * - 先使用Object的clone进行浅克隆,之后使用Arrays.copyOf复制出一份新的数据缓冲区并重置modCount
     */
    public Object clone() {
    	try {
    		ArrayList<?> v = (ArrayList<?>) super.clone();
    		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);
    	}
    }
    
    /**
     * - 获得当前List的数组形式
     * - 通过使用Arrays.copyOf和size复制数据缓冲区的实际数据,将当前List转换为一个数组对象返回
     */
    public Object[] toArray() {
    	return Arrays.copyOf(elementData, size);
    }
    
    /**
     * - 将List的数据放到指定数组里面.
     *   如果指定数组的长度小于List中的数据量,就会舍弃指定数组创建一个新数组存放数据并返回
     *   否则将数组的前size位(下标为0至size-1)覆盖存放List中的数据.第size+1位(下标为size)置为null,之后的数据保持不变
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
    	if (a.length < size)
    		// Make a new array of a's runtime type, but my contents:
    		return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    	System.arraycopy(elementData, 0, a, 0, size);
    	if (a.length > size)
    		a[size] = null;
    	return a;
    }
    
    // 根据指定的比较器进行排序,实际是使用的数组的Arrays.sort来对数据缓存区操作-触发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++;
    }
    
    // 对集合内的所有元素进行指定操作(Consumer接口指定操作--什么是Consumer?)
    @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();
        }
    }
  2. ArrayList的增删查改
    /**
     * - 是否含有某元素,可以看到ArrayList是通过IndexOf来判断是否含有对应元素的
     */
    public boolean contains(Object o) {
    	return indexOf(o) >= 0;
    }
    
    /**
     * - 获得第一个与指定元素相等的下标
     * - 如果用null的话用等号,非null用equals。采用for循环遍历数据缓冲区中有数据的区域,
     *   一但找到符合的便返回其下标(也就是说会返回第一个相等元素的下标),未找到返回-1
     */
    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;
    }
    
    /**
     * - 获得最后一个与指定元素相等的下标
     * - 如果用null的话用等号,非null用equals。采用for循环遍历数据缓冲区中有数据的区域,
     *   与indexOf不同的是进行倒序寻找,一但找到符合的便返回其下标,未找到返回-1
     */
    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;
    }
    
    /**
     * - 获得指定下标的数据
     */
    public E get(int index) {
    	// 下标越界检查
    	rangeCheck(index);
    	// 获得数据缓存区的数据
    	return elementData(index);
    }
    
    
    /**
     * - 下标越界检查
     */
    private void rangeCheck(int index) {
    	// 如果要检查的下标大于等于size。抛出IndexOutOfBoundsException
    	if (index >= size)
    		throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    /**
     * - 数组越界异常的errorMsg构造
     */
    private String outOfBoundsMsg(int index) {
    	return "Index: "+index+", Size: "+size;
    }
    
    // 从数据缓冲区elementData获取指定下标的数据
    E elementData(int index) {
    	return (E) elementData[index];
    }
    
    /**
     * - 设置指定下标为指定数据,并返回旧数据(set的动作不会改变modCount)
     */
    public E set(int index, E element) {
    	// 下标越界检查
    	rangeCheck(index);
    	// 获得旧数据oldValue
    	E oldValue = elementData(index);
    	// 用新数据覆盖旧数据
    	elementData[index] = element;
    	// 返回旧数据
    	return oldValue;
    }
    
    /**
     * - 添加指定元素到List的末尾
     */
    public boolean add(E e) {
    	// 确保数据缓冲区的大小,上面有其相关的操作(这里会有modCount的+1)
    	ensureCapacityInternal(size + 1);  // Increments modCount!!
    	// 将指定元素放到size位,然后size+1
    	elementData[size++] = e;
    	return true;
    }
    
    /**
     * - 插入指定元素到指定位置.(set是覆盖,add是插入)
     */
    public void add(int index, E element) {
    	// 越界检查(For Add)
    	rangeCheckForAdd(index);
    	// 确保数据缓冲区的大小(这里会有modCount的+1)
    	ensureCapacityInternal(size + 1);  // Increments modCount!!
    	// 将index及之后的数据向后推移一位(index至end赋值到index+1至end+1的位置)
    	System.arraycopy(elementData, index, elementData, index + 1,
    					 size - index);
    	// 将指定数据放到指定位置
    	elementData[index] = element;
    	// size +1 
    	size++;
    }
    
    /**
     * -对Add的越界检查来说,index是可以等于size的。指定下标add时间相当于放到List的末尾
     */
    private void rangeCheckForAdd(int index) {
    	if (index > size || index < 0)
    		throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    
    /**
     *  - 添加指定集合中的元素到List当中(从末尾添加)
     */
    public boolean addAll(Collection<? extends E> c) {
    	Object[] a = c.toArray();
    	int numNew = a.length;
    	// 确保数据缓冲区的大小
    	ensureCapacityInternal(size + numNew);  // Increments modCount
    	// 将c的数据赋值到elementData中
    	System.arraycopy(a, 0, elementData, size, numNew);
    	// 更新size
    	size += numNew;
    	return numNew != 0;
    }
    /**
     *  - 添加指定集合中的元素到List当中(从指定位置添加)
     */
    public boolean addAll(int index, Collection<? extends E> c) {
    	// 下标越界检查
    	rangeCheckForAdd(index);
    
    	Object[] a = c.toArray();
    	int numNew = a.length;
    	// 确保数据缓冲区的大小
    	ensureCapacityInternal(size + numNew);  // Increments modCount
    
    	int numMoved = size - index;
    	// 如果指定的index不在末尾
    	if (numMoved > 0)
    		// 数据向后移动腾出位置
    		System.arraycopy(elementData, index, elementData, index + numNew,
    						 numMoved);
    	// 将c中的数据依次放到腾出的位置上
    	System.arraycopy(a, 0, elementData, index, numNew);
    	// 更新size
    	size += numNew;
    	return numNew != 0;
    }
    
    /**
     * - 根据下标移除数据[触发modCount]
     */
    public E remove(int index) {
    	// 下标越界检查
    	rangeCheck(index);
    	// modCount增加标识结构改变
    	modCount++;
    	// 获得这个下标的旧值
    	E oldValue = elementData(index);
    
    	int numMoved = size - index - 1;
    	// 如果不是最后一个就把index之后的数据整体前移
    	if (numMoved > 0)
    		System.arraycopy(elementData, index+1, elementData, index,
    						 numMoved);
        // 置空最后一位,同时更新size							
    	elementData[--size] = null; // clear to let GC do its work
    	return oldValue;
    }
    
    /**
     * - remove的越界检查就和add不一样了。remove的越界检查下标不允许等于size
     */
    private void rangeCheck(int index) {
    	if (index >= size)
    		throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    
    /**
     * - 先遍历找到第一个相等元素的index(null用=非null用equals),然后用fastRemove移除(fastRemove触发modCount)
     */
    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;
    }
    
    
    /*
     * - fastRemove和remove(index)操作类似,只是少了越界检查(调用方已经做了)和旧值返回[触发modCount]
     */
    private void fastRemove(int index) {
    	// modCount增加标识结构改变
    	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
    }
    
    /**
     * - 循环把数据缓冲区的数据都置为null,数据缓冲区大小不会改变[触发modCount]
     */
    public void clear() {
    	modCount++;
    
    	// clear to let GC do its work
    	for (int i = 0; i < size; i++)
    		elementData[i] = null;
    
    	size = 0;
    }
    
    
    /**
     * - 通过System.arraycopy将数据缓冲区中的元素进行移位。并将多出来的长度置为null来快速GC掉无效数据,
     *   范围越界时抛出IndexOutOfBoundsException[触发modCount].实质上是数据缓冲区的数组覆盖移位
     */
    protected void removeRange(int fromIndex, int toIndex) {
    	modCount++;
    	int numMoved = size - toIndex;
    	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;
    }
    
    /**
     * - 移除指定元素,使用到batchRemove
     */
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }
    /**
     * - 保留指定元素,使用到batchRemove
     */
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }
    /**
     * - 通过complement来判断是保留还是移除c中的元素。
     * - 具体执行为遍历数据缓冲区的每个元素,判断c中是否含有指定元素。如果符合条件则保留该元素。
     * - 因为保留的数据量一定是小于等于原数据量的,因此依然采用覆盖数组的方式
     */
    private boolean                                                                                                                                                                                                                                                                                                                                                                                                                           (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)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            // 这个地方主要是针对异常情况,异常点之后的数据会全部保存
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            // 如果w不等于size,说明有元素被移除,此时将后面的元素置为null以快速GC。
            /*后面置为null并不是防止数据干扰,因为有size的存在,用户根本访问不到后面的数据*/
            if (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;
    }
    
    // 移除所有符合条件的元素.:先通过filter找到所有的下标,然后再通过遍历覆盖的方式来进行remove-触发modCount
    @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;
    }
    
    // 通过operator对所有的元素进行替换操作(遍历缓存区,覆盖数组元素)-触发modCount
    @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++;
    }

     

  3. ArrayList自身的迭代与拆分(什么是Spliterator?)
    /**
     * - ArrayList的元素迭代器
     * -   就是通过记录下标的方式来遍历集合。cursor用来记录下一个下标值,lastRet记录上一次返回的下标值
     * -   expectedModCount用来记录属于迭代器的modCount,以便于并发情况下抛出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
        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来移除元素。同时也会重置lastRet使得不能连续remove,每次remove之前都需要调用next。
        // 重置expectedModCount也是为什么在迭代期间使用迭代器的remove不会触发ConcurrentModificationException的原因
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();
    
            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    
        // 对迭代器剩下的元素执行特定操作(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;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                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();
        }
    }
    
    /**
     * - 比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;
        }
        // 前一个元素
        @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();
            }
        }
    }
    
    // 返回一个SubList
    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 + ")");
    }
    // SubList拥有正常List的所有特性,他就是集合的一种。SubList并不是一个新的集合,只是记录了开头和结尾下标并在实际使用时计算,实际还是原集合。原集合和subList之间的任意改动会互相影响
    private class SubList extends AbstractList<E> implements RandomAccess {
        private final AbstractList<E> parent;
        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;
            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;
        }
       /**略去List的常用操作,实现和ArrayList相差无几,只是会对操作下标进行计算***/
    }
    
    // 返回集合的Spliterator。Spliterator是一个分割器。同样是使用下标的方式        什么是Spliterator?
    @Override
    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; // current index, modified on advance/split
        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,指定数据缓存区,开始和结束下标,以及指定ModCount
        */
        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;
            if ((hi = fence) < 0) {
                if ((lst = list) == null)
                    hi = fence = 0;
                else {
                    expectedModCount = lst.modCount;
                    hi = fence = lst.size;
                }
            }
            return hi;
        }
    
        // 进行切割-创一个拥有新下标和围栏的ArrayListSpliterator。   trySplit的详细解释请查看Spliterator
        public ArrayListSpliterator<E> trySplit() {
            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); 
        // expectedModCount可以看到这里modCount使用是expectedModCount,而不是原集合list的modCount,标识modCount基础初次切割,而不是后续的子切割
        }
    
        // 对当前下标元素进行指定操作.且会触发modCount。也就是说原集合有变动会导致抛出ConcurrentModificationException异常。
        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;
        }
        // 对剩余元素进行指定操作(index会直接记录到末尾)
        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;
        }
    }
    

     

 

yue_hu 发布了29 篇原创文章 · 获赞 11 · 访问量 4万+ 私信 关注

标签:index,return,int,ArrayList,elementData,Collection,modCount,size
来源: https://blog.csdn.net/yue_hu/article/details/86527536