java 集合类深入理解
来源:互联网 发布:云南大学 知乎 编辑:程序博客网 时间:2024/05/21 12:39
2017-08-07
package collection.list;import java.util.AbstractList;import java.util.Arrays;import java.util.BitSet;import java.util.Collection;import java.util.Comparator;import java.util.ConcurrentModificationException;import java.util.Iterator;import java.util.List;import java.util.ListIterator;import java.util.NoSuchElementException;import java.util.Objects;import java.util.RandomAccess;import java.util.Spliterator;import java.util.function.Consumer;import java.util.function.Predicate;import java.util.function.UnaryOperator;/** * 可变数组实现了List接口.实现了所有的可选列表操作, 并且允许所有元素, 包括null. * 除了实现List接口外, 此类还提供一些方法来操作内部用来存储列表的数组的大小(此类 约等效于 Vector, 除了此类是不同步的.) * size,isEmpty,get,set,iterator,listIterator 操作都以固定时间运行. * add 操作以分摊的固定时间 运行,也就是说,添加 n 个元素需要 O(n) 时间。 * 其他所有操作都以线性时间运行(大体上讲)。与用于 LinkedList 实现的常数因子相比,此实现的常数因子较低。 * * 对一个LinkedList做随机访问所消耗的时间与这个list的大小是成比例的。在ArrayList中进行随机访问所消耗的时间是固定的。 * * 每个 ArrayList 实例都有一个容量. 该容量是指用来存储列表元素的数组的大小. 它总是至少等于列表的大小. * 随着向 ArrayList 中不断添加元素,其容量也自动增长. * 并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。 * * 在添加大量元素前,应用程序可以使用 ensureCapacity 操作来增加 ArrayList 实例的容量。 * 这可以减少递增式再分配的数量。 * * 注意:此实现不是同步的 * * 如果多个线程同时访问一个 ArrayList 实例,而其中至少一个线程从结构上修改了列表,那么它必须 保持外部同步。 * (结构上的修改是指任何添加或删除一个或多个元素的操作,或者显式调整底层数组的大小;仅仅设置元素的值不是结构上的修改。) * * 这一般通过对自然封装该列表的对象进行同步操作来完成 * 如果不存在这样的对象,则应该使用 Collections.synchronizedList 方法将该列表“包装”起来。 * 这最好在创建时完成,以防止意外对列表进行不同步的访问: * List list = Collections.synchronizedList(new ArrayList(...)); * * 此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后, * 除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改, * 迭代器都会抛出 ConcurrentModificationException。 * 因此,面对并发的修改,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。 * * 注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。 * 快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。 * 因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。 * * * Java Collections Framework * * @author Josh Bloch * @author Neal Gafter * @see Collection * @see List * @see LinkedList * @see Vector * @since 1.2 */public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ /** * 序列版本号 */ private static final long serialVersionUID = 8683452581122892189L; /** * 默认初始容量 */ private static final int DEFAULT_CAPACITY = 10; /** * 被用于空实例的共享空数组实例 */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * 被用于默认大小的空实例的共享数组实例。 * 其与EMPTY_ELEMENTDATA的区别是:当我们向数组中添加第一个元素时,知道数组该扩充多少。 */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** * ArrayList元素的数组缓冲区存储,ArrayList的容量是该Object[]类型数组的长度. * 当第一个元素被添加时,任何空ArrayList中的 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * 将会被扩充到 DEFAULT_CAPACITY(默认容量)。 */ transient Object[] elementData; // 没有private是为了简化嵌套类访问 /** * ArrayList的大小(指其所含的元素个数) * @serial */ private int size; /** * 构造一个指定初始容量的空列表 * * @param initialCapacity 初始化容器大小 * @throws 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 */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } /** * 构造一个包含指定collection的元素的列表,这些元素按照该collection的迭代器返回的顺序排列的 * * @param c 包含用于去构造ArrayList的元素的collection * @throws NullPointerException 如果指定的collection为空 */ public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray 可能 (不确定) 不返回 Object[] if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 替换空数组 this.elementData = EMPTY_ELEMENTDATA; } } /** * 调整size 和当前List列表保存的实际元素大小一样 应用程序可以使用此操作来最小化 ArrayList 实例的存储量。 */ public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } } /** * public方法,让用户能手动设置ArrayList的容量 * * @param minCapacity 期望的最小容量 */ public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // 如果不为默认空表,则为任意尺寸 ? 0 // 大于默认空表的时候,会有默认size大小 : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } /** * 用于添加元素时,确保数组容量 * @param minCapacity 期望的最小容量 */ private void ensureCapacityInternal(int minCapacity) { //若为空数组的情况比较 初始化容器大小和期望的最小容量 取最大 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } /** * 如果参数大于数组容量,就增加数组容量 * @param minCapacity 期望的最小容量 */ private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } /** * 数组分配的最大大小 * 一些 vm 储备 头关键字 数组中。 * 试图分配较大的数组可能导致 OutOfMemoryError: 请求数组容量超过 JVM 限制 */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * 增加容量来确保数据列表能达到指定的最小容量参数 * * @param minCapacity 所需的最小容量 */ private void grow(int minCapacity) { //元素列表的容量 int oldCapacity = elementData.length; //预设容量增加一半 int newCapacity = oldCapacity + (oldCapacity >> 1); //比较按机制正常扩充容量和所需最小容量大小 if (newCapacity - minCapacity < 0) //若所需最小容量大于正常扩充容量,则以所需最小容量为准 newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) //如果超出容量最大值,则获取最大容量 newCapacity = hugeCapacity(minCapacity); //最小的数值是通常接近容量,因此这是正确的 elementData = Arrays.copyOf(elementData, newCapacity); } /** * 检查是否溢出,若没有溢出,返回最大整数值或默认最大值 * @param minCapacity 所需的最小容量 * @return 最大容量 */ private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } /** * 返回此列表的元素数量 * * @return 列表的元素数量 */ public int size() { return size; } /** * 如果这个列表不包含任何元素返回true * * @return true */ public boolean isEmpty() { return size == 0; } /** * 如果此列表中包含指定的元素,则返回 true。 * 更确切地讲,当且仅当此列表包含至少一个满足 (o==null ? e==null : o.equals(e)) 的元素 e 时,则返回 true。 * * 接口 Collection<E> 中的 contains * 接口 List<E> 中的 contains * 类 AbstractCollection<E> 中的 contains * * @param o - 测试此列表中是否存在的元素 * @return 如果此列表包含特定的元素,则返回 true */ public boolean contains(Object o) { return indexOf(o) >= 0; } /** * 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。 * 更确切地讲,返回满足 (o==null ? get(i)==null : o.equals(get(i))) * 的最低索引 i ,如果不存在此类索引,则返回 -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; } /** * 返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。 * 更确切地讲,返回满足 (o==null ? get(i)==null : o.equals(get(i))) 的最高索引 i, * 如果不存在此类索引,则返回 -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; } /** * 返回此 ArrayList 实例的浅表副本。(不复制这些元素本身。) * * 类 Object 中的 clone * * @return ArrayList 实例的一个副本 */ 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); } } /** * 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。 * 由于此列表不维护对返回数组的任何引用,因而它将是“安全的”。(换句话说,此方法必须分配一个新的数组)。因此,调用者可以自由地修改返回的数组。 * 此方法担当基于数组的 API 和基于 collection 的 API 之间的桥梁。 * * 接口 Collection<E> 中的 toArray * 接口 List<E> 中的 toArray * 类 AbstractCollection<E> 中的 toArray * * @return 包含此列表中所有元素的数组(按适当顺序) * */ public Object[] toArray() { return Arrays.copyOf(elementData, size); } /** * 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。 * 如果指定的数组能容纳列表,则将该列表返回此处。否则,将分配一个具有指定数组的运行时类型和此列表大小的新数组。 * * 如果指定的数组能容纳队列,并有剩余的空间(即数组的元素比队列多),那么会将数组中紧接 collection 尾部的元素设置为 null。 * (仅 在调用者知道列表中不包含任何 null 元素时才能用此方法确定列表长度)。 * * 接口 Collection<E> 中的 toArray * 接口 List<E> 中的 toArray * 类 AbstractCollection<E> 中的 toArray * * @param a - 要在其中存储列表元素的数组(如果它足够大);否则,为此分配一个具有相同运行时类型的新数组。 * @return 包含列表元素的数组 * @throws ArrayStoreException - 如果指定数组的运行时类型不是此列表每个元素的运行时类型的超类型 * @throws NullPointerException - 如果指定数组为 null */ @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) // 创建一个新数组的运行时类型的,但我的内容: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } /** * 位置访问操作 * @param index 索引 * @return 返回的元素 */ @SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; } /** * 返回此列表中指定位置上的元素。 * * 接口 List<E> 中的 get * 类 AbstractList<E> 中的 get * * @param index - 要返回元素的索引 * @return 此列表中指定位置上的元素 * @throws IndexOutOfBoundsException - 如果索引超出范围 ( index < 0 || index >= size()) */ public E get(int index) { rangeCheck(index); return elementData(index); } /** * 用指定的元素替代此列表中指定位置上的元素。 * * 接口 List<E> 中的 set * 类 AbstractList<E> 中的 set * * * @param index - 要替代的元素的索引 * @param element - 存储在指定位置上的元素 * @return 以前位于该指定位置上的元素 * @throws IndexOutOfBoundsException - 如果索引超出范围 ( index < 0 || index >= size()) */ public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } /** * 将指定的元素添加到此列表的尾部。 * * 接口 Collection<E> 中的 add * 接口 List<E> 中的 add * 类 AbstractList<E> 中的 add * * @param e - 要添加到此列表中的元素 * @return true(按照 Collection.add(E) 的指定) */ public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } /** * 将指定的元素插入此列表中的指定位置。向右移动当前位于该位置的元素(如果有)以及所有后续元素(将其索引加 1)。 * * 接口 List<E> 中的 add * 类 AbstractList<E> 中的 add * * @param index - 指定元素所插入位置的索引 * @param element - 要插入的元素 * @throws IndexOutOfBoundsException - 如果索引超出范围 ( index < 0 || index > 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++; } /** * 这个列表中删除指定位置的元素 * 任何后续元素转移到左(减去一个来自他们的指标)。 * * 接口 List<E> 中的 remove * 类 AbstractList<E> 中的 remove * * @param index - 要移除的元素的索引 * @return 从列表中移除的元素 * @throws IndexOutOfBoundsException - 如果索引超出范围 ( index < 0 || index >= size()) */ public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); 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 return oldValue; } /** * 移除此列表中首次出现的指定元素(如果存在)。如果列表不包含此元素,则列表不做改动。 * 更确切地讲,移除满足 (o==null ? get(i)==null : o.equals(get(i))) 的最低索引的元素(如果存在此类元素)。 * 如果列表中包含指定的元素,则返回 true(或者等同于这种情况:如果列表由于调用而发生更改,则返回 true)。 * * 接口 Collection<E> 中的 remove * 接口 List<E> 中的 remove * 类 AbstractCollection<E> 中的 remove * * @param o - 要从此列表中移除的元素(如果存在) * @return 如果此列表包含指定的元素,则返回 true * */ 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; } /* * 快速删除指定位置的值,之所以叫快速,应该是不需要检查和返回值,因为只内部使用 */ 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; // 清理来让GC工作 } /** * 清空数组,把每一个值设为null,方便垃圾回收(不同于reset,数组默认大小有改变的话不会重置) */ public void clear() { modCount++; // 清理来让GC工作 for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } /** * 将该 collection 中的所有元素添加到此列表的尾部, 按照指定 collection 的迭代器所返回的元素顺序. * 如果正在进行此操作时修改指定的 collection ,那么此操作的行为是不确定的。 * (这意味着如果指定的 collection 是此列表且此列表是非空的,那么此调用的行为是不确定的) * * 接口 Collection<E> 中的 addAll * 接口 List<E> 中的 addAll * 类 AbstractCollection<E> 中的 addAll * * @param c - 包含要添加到此列表中的元素的 collection * @return 如果此列表由于调用而发生更改,则返回 true * @throws NullPointerException - 如果指定的 collection 为 null */ 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; } /** * 从指定的位置开始,将指定 collection 中的所有元素插入到此列表中 * 向右移动当前位于该位置的元素(如果有)以及所有后续元素(增加其索引) * 新元素将按照指定 collection 的迭代器所返回的元素顺序出现在列表中 * * 接口 List<E> 中的 addAll * 类 AbstractList<E> 中的 addAll * * @param index - 插入指定 collection 中的首个元素的位置索引 * @param c - 包含要添加到此列表中元素的 collection * @return 如果此列表由于调用而发生更改,则返回 true * @throws IndexOutOfBoundsException - 如果索引超出范围 ( index < 0 || index > size()) * @throws NullPointerException - 如果指定的 collection 为 null */ 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; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } /** * * 移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。向左移动所有后续元素(减小其索引)。 * 此调用将列表缩短了 (toIndex - fromIndex) 个元素。(如果 toIndex==fromIndex,则此操作无效。) * * 类 AbstractList<E> 中的 removeRange * * @param fromIndex - 要移除的首个元素的索引 * @param toIndex - 最后一个要移除的元素后面那个元素的索引 */ 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; } /** * 检查给定的索引范围.如果不是,适当抛出一个运行时异常. * 这个方法不检查负数的: 他是立即访问数组的,如果指数是负的,抛出ArrayIndexOutOfBoundsException */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 一个版本 rangeCheck 被使用 add and addAll. */ private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 构造一个 IndexOutOfBoundsException 详细信息 * 有许多可能来处理错误的code,这个概述执行最好在服务端和客户端VMs */ private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; } /** * 从这个列表中移除所有元素包含在指定的集合。 * * @param c - 包含要添加到此列表中元素的 collection * @return 如果这个list列表改变了,则返回true * @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection * (<a href="Collection.html#optional-restrictions">optional</a>) * @throws NullPointerException if this list contains a null element and the * specified collection does not permit null elements * (<a href="Collection.html#optional-restrictions">optional</a>), * or if the specified collection is null * @see Collection#contains(Object) */ public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, false); } /** * 只保留在这个列表的元素包含在指定的集合。 * 换句话说,从这个列表中移除所有元素不包含在指定的集合。 * * @param c collection containing elements to be retained in this list * @return {@code true} if this list changed as a result of the call * @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection * (<a href="Collection.html#optional-restrictions">optional</a>) * @throws NullPointerException if this list contains a null element and the * specified collection does not permit null elements * (<a href="Collection.html#optional-restrictions">optional</a>), * or if the specified collection is null * @see Collection#contains(Object) */ public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); } /** * 批量移除 * @param c * @param complement * @return */ private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // 保持行为与AbstractCollection的兼容性, // 即使c.contains()抛出。 if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } 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; } /** * 保存数组实例的状态到一个流(即它序列化)。写入过程数组被更改会抛出异常 * * @serialData The length of the array backing the <tt>ArrayList</tt> * instance is emitted (int), followed by all of its elements * (each an <tt>Object</tt>) in the proper order. */ 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]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } /** * 保存这个状态下的实例变成二进制流存储(序列化) */ 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(); } } } /** * 返回一个list列表的迭代器 (在适当的顺序), 从列表中指定的位置。 * 指定的索引显示返回的第一个元素,将初始调用{ @link ListIterator #下一个下一个}。 * An initial call to {@link ListIterator#previous previous} would return the element with the specified index minus one. * * 返回的列表迭代器是快速失败的 * * @throws IndexOutOfBoundsException {@inheritDoc} */ public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } /** * 返回一个list列表的迭代器 (在适当的顺序) * * 返回的列表迭代器是快速失败的 * * @see #listIterator(int) */ public ListIterator<E> listIterator() { return new ListItr(0); } /** * 返回一个迭代器在这个列表的元素序列。 * * 返回的列表迭代器是快速失败的 * * @return 迭代器在这个列表的元素序列 */ public Iterator<E> iterator() { return new Itr(); } /** * 通用的迭代器实现 */ 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]; } 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(); } } @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(); } } /** * ListIterator迭代器实现 */ 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(); } } } /** * 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。(如果 fromIndex 和 toIndex 相等,则返回的列表为空)。 * 返回的列表由此列表支持,因此返回列表中的非结构性更改将反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。 * * 此方法省去了显式范围操作(此操作通常针对数组存在)。 * 通过传递 subList 视图而非整个列表,期望列表的任何操作可用作范围操作。例如,下面的语句从列表中移除了元素的范围: * list.subList(from, to).clear(); * * 可以对 indexOf 和 lastIndexOf 构造类似的语句,而且 Collections 类中的所有算法都可以应用于 subList。 * * 如果支持列表(即此列表)通过任何其他方式(而不是通过返回的列表)从结构上修改, * 则此方法返回的列表语义将变为未定义(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果)。 * * @throws IndexOutOfBoundsException - 端点索引值超出范围 (fromIndex < 0 || toIndex > size) * @throws IllegalArgumentException - 端点索引顺序颠倒 (fromIndex > toIndex) * */ public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } /** * 校验参数 * @param fromIndex * @param toIndex * @param size */ 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; 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; } 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; } protected void removeRange(int fromIndex, int toIndex) { checkForComodification(); parent.removeRange(parentOffset + fromIndex, parentOffset + toIndex); this.modCount = parent.modCount; this.size -= toIndex - fromIndex; } public boolean addAll(Collection<? extends E> c) { return addAll(this.size, c); } 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; } public Iterator<E> iterator() { return listIterator(); } 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); } } /** * 按顺序那每个元素交给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(); } } /** * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em> * and <em>fail-fast</em> {@link Spliterator} over the elements in this * list. * * <p>The {@code Spliterator} reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}. * Overriding implementations should document the reporting of additional * characteristic values. * * @return a {@code Spliterator} over the elements in this list * @since 1.8 */ @Override public Spliterator<E> spliterator() { return new ArrayListSpliterator<E>(this, 0, -1, 0); } /** Index-based split-by-two, lazily initialized Spliterator */ static final class ArrayListSpliterator<E> implements Spliterator<E> { /* * If ArrayLists were immutable, or structurally immutable (no * adds, removes, etc), we could implement their spliterators * with Arrays.spliterator. Instead we detect as much * interference during traversal as practical without * sacrificing much performance. We rely primarily on * modCounts. These are not guaranteed to detect concurrency * violations, and are sometimes overly conservative about * within-thread interference, but detect enough problems to * be worthwhile in practice. To carry this out, we (1) lazily * initialize fence and expectedModCount until the latest * point that we need to commit to the state we are checking * against; thus improving precision. (This doesn't apply to * SubLists, that create spliterators with current non-lazy * values). (2) We perform only a single * ConcurrentModificationException check at the end of forEach * (the most performance-sensitive method). When using forEach * (as opposed to iterators), we can normally only detect * interference after actions, not before. Further * CME-triggering checks apply to all other possible * violations of assumptions for example null or too-small * elementData array given its size(), that could only have * occurred due to interference. This allows the inner loop * of forEach to run without any further checks, and * simplifies lambda-resolution. While this does entail a * number of checks, note that in the common case of * list.stream().forEach(a), no checks or other computation * occur anywhere other than inside forEach itself. The other * less-often-used methods cannot take advantage of most of * these streamlinings. */ 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(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; } 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); } 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; } 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; } } /** * 移除集合中满足给定条件的所有元素,错误或者运行时异常发生在迭代时或者把条件传递给调用者的时候。 * * @implSpec * 默认的实现贯穿了使用迭代器iterator的集合的所有元素。每一个匹配的元素都将被用Iterator接口中的 * remove()方法移除。如果集合的迭代器不支持移除,则在第一次匹配时就会抛出异常 UnsupportedOperationException * * @param filter 令元素移除成功的条件 * @return {@code true} 如果所有的元素都被移除 * @throws NullPointerException 如果有一个过滤器是空的 * @throws UnsupportedOperationException 如果元素不能被从该集合中移除。如果一个匹配元素不能被移除, * 通常来说,它就不支持移除操作,这时可能抛出这个异常。 * @since 1.8 */ @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; } @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++; } /** * 排序 * @param c */ @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++; }}
阅读全文
0 0
- java 集合类深入理解
- java 集合类深入理解
- java 集合类深入理解
- java 集合类深入理解
- 深入理解Java集合
- Java深入 - 深入理解Java集合
- 集合类的深入理解
- 深入理解java集合的底层操作
- 深入理解Java之集合框架
- 深入理解Java之集合框架
- JAVA集合深入理解,多图解析。
- 1.深入理解java集合List
- 《深入理解Java集合框架》系列文章
- Java 集合深入理解(3):Collection
- Java 集合深入理解(5):AbstractCollection
- Java 集合深入理解(6):AbstractList
- Java 集合深入理解(7):ArrayList
- Java 集合深入理解(8):AbstractSequentialList
- 解剖getchar
- 试密码(20)
- Linux实现的IEEE 802.1Q及VLAN/Trunk以及三层交换
- iOS开发 UIReferenceLibraryViewController(词典)的使用
- winForm圆角矩形及C++builderForm圆角设计
- java 集合类深入理解
- 2017多校四 1007题 hdu 6073 Matching In Multiplication 拓扑排序 + 找环
- 循环队列
- Java8 默认方法 default method
- 残缺的棋盘(dijkstra算法)
- 理解面向对象
- 多目标及多分类区别及交叉熵问题
- 文章标题
- android开机