/** * Resizable-array implementation of the <tt>List</tt> interface. Implements * all optional list operations, and permits all elements, including * <tt>null</tt>. In addition to implementing the <tt>List</tt> interface, * this class provides methods to manipulate the size of the array that is * used internally to store the list. (This class is roughly equivalent to * <tt>Vector</tt>, except that it is unsynchronized.) * * <p>The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>, * <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant * time. The <tt>add</tt> operation runs in <i>amortized constant time</i>, * that is, adding n elements requires O(n) time. All of the other operations * run in linear time (roughly speaking). The constant factor is low compared * to that for the <tt>LinkedList</tt> implementation. * * <p>Each <tt>ArrayList</tt> instance has a <i>capacity</i>. The capacity is * the size of the array used to store the elements in the list. It is always * at least as large as the list size. As elements are added to an ArrayList, * its capacity grows automatically. The details of the growth policy are not * specified beyond the fact that adding an element has constant amortized * time cost. * * <p>An application can increase the capacity of an <tt>ArrayList</tt> instance * before adding a large number of elements using the <tt>ensureCapacity</tt> * operation. This may reduce the amount of incremental reallocation. * * <p><strong>Note that this implementation is not synchronized.</strong> * If multiple threads access an <tt>ArrayList</tt> instance concurrently, * and at least one of the threads modifies the list structurally, it * <i>must</i> be synchronized externally. (A structural modification is * any operation that adds or deletes one or more elements, or explicitly * resizes the backing array; merely setting the value of an element is not * a structural modification.) This is typically accomplished by * synchronizing on some object that naturally encapsulates the list. * * If no such object exists, the list should be "wrapped" using the * {@link Collections#synchronizedList Collections.synchronizedList} * method. This is best done at creation time, to prevent accidental * unsynchronized access to the list:<pre> * List list = Collections.synchronizedList(new ArrayList(...));</pre> * * <p><a name="fail-fast"> * The iterators returned by this class's {@link #iterator() iterator} and * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:</a> * if the list is structurally modified at any time after the iterator is * created, in any way except through the iterator's own * {@link ListIterator#remove() remove} or * {@link ListIterator#add(Object) add} methods, the iterator will throw a * {@link ConcurrentModificationException}. Thus, in the face of * concurrent modification, the iterator fails quickly and cleanly, rather * than risking arbitrary, non-deterministic behavior at an undetermined * time in the future. * * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the * presence of unsynchronized concurrent modification. Fail-fast iterators * throw {@code ConcurrentModificationException} on a best-effort basis. * Therefore, it would be wrong to write a program that depended on this * exception for its correctness: <i>the fail-fast behavior of iterators * should be used only to detect bugs.</i> * * <p>This class is a member of the * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch * @author Neal Gafter * @see Collection * @see List * @see LinkedList * @see Vector * @since 1.2 */
/** * Shared empty array instance used for empty instances. */ privatestaticfinal Object[] EMPTY_ELEMENTDATA = {}; // 初始化空数组
/** * Shared empty array instance used for default sized empty instances. We * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when * first element is added. */ privatestaticfinal Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 和 EMPTY_ELEMENTDATA 做区分
/** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ // 真正存放数据的数组,transient 防止进行序列化,既然元素不支持序列化,那么类上为什么又实现了 Serilizable 接口呢 // 这里是自己重写了序列化方法,节省了 50% 序列化的空间 transient Object[] elementData; // non-private to simplify nested class access
/** * The size of the ArrayList (the number of elements it contains). * * @serial */ // ArrayList 中包含的元素个数 privateint size;
/** * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity * is negative */ // 带初始容量的构造器 publicArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = newObject[initialCapacity]; } elseif (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { thrownewIllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
/** * Constructs an empty list with an initial capacity of ten. */ // 空参构造期 publicArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
// ... }
add(E e) 以及扩容机制
当我们初始化一个容量为 0 的 ArrayList 的容量 ArrayList<Object> list = new ArrayList<>(0);
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return <tt>true</tt> (as specified by {@link Collection#add}) */ publicbooleanadd(E e) { // 1. 确保内部容量 ensureCapacityInternal(size + 1); // Increments modCount!! // 2. 添加元素到 elementData 中,同时 size + 1 elementData[size++] = e; returntrue; }
/** * The maximum size of array to allocate. * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ privatestaticfinalintMAX_ARRAY_SIZE= Integer.MAX_VALUE - 8;
/** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ privatevoidgrow(int minCapacity) { // overflow-conscious code // 旧容量 intoldCapacity= elementData.length; // 新容量,扩容为旧容量的 近似 1.5 倍【注意】 intnewCapacity= oldCapacity + (oldCapacity >> 1); // 扩容之后的新容量还是 小于 我们传入的最小容量,那把 minCapacity 作为我们的新容量 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 如果 新容量 大于 最小数组大小(int 最大值 - 8),那么执行 hugeCapacity(minCapacity); 扩容为 int 最大值 if (newCapacity - MAX_ARRAY_SIZE > 0) // Integer.MAX_VALUE - 8; newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: // 开辟新数组,并将原数组的内容拷贝到新数组中,最后再赋值给 elementData elementData = Arrays.copyOf(elementData, newCapacity); }
/** * Constructs an empty list with an initial capacity of ten. */ publicArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // DEFAULTCAPACITY_EMPTY_ELEMENTDATA 赋值给 elementData }
当我们代码中要返回空 List 的时候才会用到,public static final List EMPTY_LIST = new EmptyList<>(); 在 javac 编译成 class 文件的时候就已经初始化了,比 new ArrayList() 每次返回空 List 要好,因为不需要重新创建对象。
/** * Trims the capacity of this <tt>ArrayList</tt> instance to be the * list's current size. An application can use this operation to minimize * the storage of an <tt>ArrayList</tt> instance. */ publicvoidtrimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } }
/** * Returns <tt>true</tt> if this list contains the specified element. * More formally, returns <tt>true</tt> if and only if this list contains * at least one element <tt>e</tt> such that * <tt>(o==null ? e==null : o.equals(e))</tt>. * * @param o element whose presence in this list is to be tested * @return <tt>true</tt> if this list contains the specified element */ publicbooleancontains(Object o) { return indexOf(o) >= 0; // 这里调用 indexOf(o),判断返回索引是否 大于等于 0,如果是则包含,否则不包含 }
indexOf(int index) 源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/** * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the lowest index <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, * or -1 if there is no such index. */ publicintindexOf(Object o) { if (o == null) { // 如果是空,遍历等于空的位置,找到第一个返回 for (inti=0; i < size; i++) if (elementData[i]==null) return i; } else { // 如果不是空,同样是 for 循环遍历,找到第一个返回 for (inti=0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; // 找不到返回 -1 }
lastIndexOf(int index) 源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/** * Returns the index of the last occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the highest index <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, * or -1 if there is no such index. */ publicintlastIndexOf(Object o) { if (o == null) { for (inti= size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (inti= size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; }
/** * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The * elements themselves are not copied.) * * @return a clone of this <tt>ArrayList</tt> instance */ public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); // 调用父类 clone() v.elementData = Arrays.copyOf(elementData, size); // Arrays.copy 拷贝 v.modCount = 0; // 克隆之后认为是一个新的 ArrayList,没有被修改过 return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable thrownewInternalError(e); } }
/** * Returns an array containing all of the elements in this list * in proper sequence (from first to last element). * * <p>The returned array will be "safe" in that no references to it are * maintained by this list. (In other words, this method must allocate * a new array). The caller is thus free to modify the returned array. * * <p>This method acts as bridge between array-based and collection-based * APIs. * * @return an array containing all of the elements in this list in * proper sequence */ public Object[] toArray() { return Arrays.copyOf(elementData, size); }
// 泛型实现 T 是类型,E 是元素,U 是 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 System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }
/** * Returns the element at the specified position in this list. * * @param index index of the element to return * @return the element at the specified position in this list * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { rangeCheck(index); // 索引范围检查,不合法抛出下标越界异常
return elementData(index); // 返回索引对应的值 }
/** * Checks if the given index is in range. If not, throws an appropriate * runtime exception. This method does *not* check if the index is * negative: It is always used immediately prior to an array access, * which throws an ArrayIndexOutOfBoundsException if index is negative. */ privatevoidrangeCheck(int index) { if (index >= size) // 索引不合法抛出 IndexOutOfBoundsException 异常 thrownewIndexOutOfBoundsException(outOfBoundsMsg(index)); }
set(index)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/** * Replaces the element at the specified position in this list with * the specified element. * * @param index index of the element to replace * @param element element to be stored at the specified position * @return the element previously at the specified position * @throws IndexOutOfBoundsException {@inheritDoc} */ public E set(int index, E element) { rangeCheck(index); // 索引范围检查
/** * Inserts the specified element at the specified position in this * list. Shifts the element currently at that position (if any) and * any subsequent elements to the right (adds one to their indices). * * @param index index at which the specified element is to be inserted * @param element element to be inserted * @throws IndexOutOfBoundsException {@inheritDoc} */ publicvoidadd(int index, E element) { rangeCheckForAdd(index); // 插入索引范围检查
/** * A version of rangeCheck used by add and addAll. */ privatevoidrangeCheckForAdd(int index) { if (index > size || index < 0) // 插入索引范围检查,这里有一个优化的地方:把常用的判断条件放前边,提高性能 thrownewIndexOutOfBoundsException(outOfBoundsMsg(index)); }
/** * Constructs an IndexOutOfBoundsException detail message. * Of the many possible refactorings of the error handling code, * this "outlining" performs best with both server and client VMs. */ private String outOfBoundsMsg(int index) { return"Index: "+index+", Size: "+size; // 对于短字符串用 + 号最快,对于大量字符串拼接用 StringBuilder }
/** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). * * @param index the index of the element to be removed * @return the element that was removed from the list * @throws IndexOutOfBoundsException {@inheritDoc} */ // 根据索引删除 public E remove(int index) { rangeCheck(index); // 索引范围检查
intnumMoved= size - index - 1; // numMoved 是删除 index 上的数后需要移动的元素的个数 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); // 又是一个 arraycopy elementData[--size] = null; // clear to let GC do its work,容量 - 1 并且最后一个元素指向空,表示不可达,等待下次垃圾回收
return oldValue; }
/** * Removes the first occurrence of the specified element from this list, * if it is present. If the list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> * (if such an element exists). Returns <tt>true</tt> if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return <tt>true</tt> if this list contained the specified element */ // 删除指定对象,如果有多个,删除第一个 publicbooleanremove(Object o) { // 这里和 contains(Object o) 实现类似 // for 循环遍历,找到第一个相等的元素删除 if (o == null) { for (intindex=0; index < size; index++) if (elementData[index] == null) { fastRemove(index); // 这里调用 fastRemove() 方法进行删除当前元素 returntrue; } } else { for (intindex=0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); returntrue; } } returnfalse; }
/* * Private remove method that skips bounds checking and does not * return the value removed. */ // 发现和 remove(index) 思路一样啊,也是 arraycopy 移动元素, // 然名字是 fastRemove() 但是实现上并没有变快,就是一个名字而已,因为要多次调用,所以抽取成了一个方法 privatevoidfastRemove(int index) { modCount++; intnumMoved= size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }
clear()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/** * Removes all of the elements from this list. The list will * be empty after this call returns. */ // 清空 List publicvoidclear() { modCount++; // 清空也是一次修改 // 将每个元素置空,等待 GC 回收 // clear to let GC do its work for (inti=0; i < size; i++) elementData[i] = null;
size = 0; // size 置为 0 }
延伸:下面这段代码扩容几次?
1 2 3 4
List<Object> list = newArrayList<>(); list.add("a"); list.clear(); list.add("a");
/** * Appends all of the elements in the specified collection to the end of * this list, in the order that they are returned by the * specified collection's Iterator. The behavior of this operation is * undefined if the specified collection is modified while the operation * is in progress. (This implies that the behavior of this call is * undefined if the specified collection is this list, and this * list is nonempty.) * * @param c collection containing elements to be added to this list * @return <tt>true</tt> if this list changed as a result of the call * @throws NullPointerException if the specified collection is null */ // 向 List 中添加一个 List publicbooleanaddAll(Collection<? extends E> c) { Object[] a = c.toArray(); intnumNew= a.length; // 确保内部容量 ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); // 数组拷贝,把 a 数组放到 elementData 数组后面 size += numNew; // 元素个数 + numNew return numNew != 0; // 如果不是 0 就可以添加成功 }
/** * Inserts all of the elements in the specified collection into this * list, starting at the specified position. Shifts the element * currently at that position (if any) and any subsequent elements to * the right (increases their indices). The new elements will appear * in the list in the order that they are returned by the * specified collection's iterator. * * @param index index at which to insert the first element from the * specified collection * @param c collection containing elements to be added to this list * @return <tt>true</tt> if this list changed as a result of the call * @throws IndexOutOfBoundsException {@inheritDoc} * @throws NullPointerException if the specified collection is null */ // 向 List 的某个位置上插入一个 List publicbooleanaddAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); // 插入索引范围检查
/** * Removes from this list all of the elements whose index is between * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. * Shifts any succeeding elements to the left (reduces their index). * This call shortens the list by {@code (toIndex - fromIndex)} elements. * (If {@code toIndex==fromIndex}, this operation has no effect.) * * @throws IndexOutOfBoundsException if {@code fromIndex} or * {@code toIndex} is out of range * ({@code fromIndex < 0 || * fromIndex >= size() || * toIndex > size() || * toIndex < fromIndex}) */ // 范围删除 protectedvoidremoveRange(int fromIndex, int toIndex) { modCount++; intnumMoved= size - toIndex; // 要移动的元素个数 System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // 将 [toIndex, size) 拷贝到从 fromIndex 开始
// clear to let GC do its work intnewSize= size - (toIndex-fromIndex); for (inti= newSize; i < size; i++) { // 删除后面的元素 elementData[i] = null; } size = newSize; // 更新 size }
/** * Removes from this list all of its elements that are contained in the * specified collection. * * @param c collection containing elements to be removed from 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) */ // 从 List 中删除集合 c 中的所有元素 publicbooleanremoveAll(Collection<?> c) { Objects.requireNonNull(c); // 判断是否为空,调用的是 Object 的方法 return batchRemove(c, false); // 批量删除 }
// Object.class publicstatic <T> T requireNonNull(T obj) { if (obj == null) // 只判断了是否为 null,没有判断空 List thrownewNullPointerException(); return obj; }
privatebooleanbatchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; // 复制一份 elementData intr=0, w = 0; // 定义两个指针 booleanmodified=false; try { // complement = false,所以 for 循环的含义就是将不在 c 集合中的元素放到数组的前面,并且记录个数 w 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) { // 正常情况下上面循环执行结束 r = size System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // w == size 表示 elementData 全删 // clear to let GC do its work for (inti= w; i < size; i++) // 将 [w, size) 后面的元素全部删掉 elementData[i] = null; modCount += size - w; // 更新 modCount size = w; // 更新 size modified = true; // 修改成功 } } return modified; }
/** * Save the state of the <tt>ArrayList</tt> instance to a stream (that * is, serialize it). * * @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. */ privatevoidwriteObject(java.io.ObjectOutputStream s) throws java.io.IOException{ // Write out element count, and any hidden stuff intexpectedModCount= modCount; // 将 modCount 存一份,用于判断在 List 序列化的过程中是否有其他线程进行了修改 s.defaultWriteObject(); // 对 ObjectOutputStream 做一个初始化
// Write out size as capacity for behavioural compatibility with clone() s.writeInt(size); // 先把 size 序列化
// Write out all elements in the proper order. for (int i=0; i<size; i++) { // for 循环序列每个元素,这里太妙了!!! s.writeObject(elementData[i]); }
// 最后判断是否有并发修改异常,如果出现异常则序列化失败 // 那么如果有修改,序列化就白做了,但其实这也符合实际场景:一切对于我们的 list 的业务上的修改级别高于序列化。 if (modCount != expectedModCount) { thrownewConcurrentModificationException(); } }
/** * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, * deserialize it). */ privatevoidreadObject(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 // 先读取 List 的大小
if (size > 0) { // 如果有数据再反序列化 // be like clone(), allocate array based upon size not capacity intcapacity= calculateCapacity(elementData, size); SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity); ensureCapacityInternal(size); // 先保证容量
Object[] a = elementData; // Read in all elements in the proper order. for (int i=0; i<size; i++) { // 每次读一个对象存到 elementData 中 a[i] = s.readObject(); } } }