一、如何分析
第一次做源码分析,借鉴网上的分析方法,做一次尝试
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.内部类
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; } }