/** * 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.) 这是一个实现了List接口的可变长度的数组。实现了list接口中的全部方法,容许存放全部的元素,包括null。除了实现list接口,该类还提供了一些方法来操做数组的大小,此数组被用来存储list的数据。(这个类和vector大体至关,除了它是线程不安全的)
* * <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. * size(),isEmpty(),get(),set()方法使用的一个恒定时间(一个方法具备恒定的执行时间的,也就是代码不会由于问题规模n的变化而发生变化,时间复杂度记为O(1))。add操做花费恒定分摊时间,即插入n个元素须要o(n)的时间。 粗略的来讲全部其余操做都以线性时间运行。(即这些操做与元素的个数成线性关系,操做的时间复杂度o(n))。这些操做与LinkedList实现相比,常数因子较低。
* <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. * 每一个ArrayList的实例对象都有一个容量(capacity)。这个容量就是这个list中用来存储元素的数组的大小。它至少和list的大小同样大。当有元素被增长到集合中时,它的容量会自动增长。除了要求添加一个元素的效率为“恒定分摊时间”,对于具体实现的细节没有特别的要求。 * <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. 在大批量插入元素前,使用ensureCapacity()方法来增长集合的容量。这或许可以减小扩容增长量的大小。
* <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. * 注意这个实现类是非同步的。若是有多个线程同时操做一个ArrayList的实例。而后,至少有一个线程修改了list的结构,就必须在外部保证它的线程同步。(结构修改指的是增长或者删除一个或多个映射;若是仅仅是更改已经存在的 key和value值,不算作结构修改)。这一般须要在一个被封装好的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> * 若是没有这样的对象存在,那么就须要使用Collections.synchronizedList方法来包装这个list对象,并且最好是在建立对象的时候就进行包装,这是为了预防对这个list对象进行一些线程不一样步的操做。举个例子:List list = Collections.synchronizedList(new ArrayList(...));
* <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. * 该类的集合视图方法返回的迭代器是fail-fast机制的:在迭代器被建立后,若是list对象被结构化修改后,不管在什么时候,使用何种方法(除了迭代器自己的remove方法和add方法)来修改它,都会抛出ConcurrentModificationException.所以,面对并发修改操做时,迭代器会迅速且清晰地报错.而不是冒着在不肯定的时间作不肯定的操做的风险.
* <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> 注意,迭代器的fail-fast行为是不能保证的.通常来讲,保证非同步的同步操做是不太可能的.在最优基础上,Fail-fast迭代器会抛出ConcurrentModificationException.所以,写一个为了自身正确性而依赖于这个异常的程序是不对的.迭代器的fail-fast行为应该只是用来检测bug而已.
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
继承的类
AbstractList:抽象类,只需知道此类是List接口的简单通用实现数组
实现的接口
List:很少说了
RandomAccess:(标记接口)表明支持随机访问
Cloneable:(标记接口)表明 Object.clone() 方法能够合法地对该类实例进行按字段复制。(没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会致使抛出 CloneNotSupportedException 异常)
java.io.Serializable(标记接口)安全
protected transient int modCount = 0;
/** * Default initial capacity. * 初始默认容量 为 10 */ private static final int DEFAULT_CAPACITY = 10;
/** * Shared empty array instance used for empty instances. * * 指定该ArrayList容量为0时,返回该空数组。 */ private static final 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. * * 用于默认大小的空实例的共享空数组实例。 * 这个空数组的实例用来给无参构造使用。当调用无参构造方法,返回的是该数组。 * 将此与EMPTY_ELEMENTDATA区分开来,以便了解在添加第一个元素时要增长多少容量。 */ private static final Object[] DEFAULTCAPACITY_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. * * 存储ArrayList元素的数组缓冲区 * ArrayList的容量(capacity)就是是此数组缓冲区的长度。 * 声明为transient 不会被序列化 * 非私有 是为了方便内部类调用 */ 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;
这里提一点:前面提到size()方法时间复杂度为O(1),是由于它将size存储起来了,牺牲了空间提升了效率。数据结构
ArrayList有三个构造器并发
建立一个指定存储容量的空序列 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转换为ArrayList的构造器 这些元素是按照该 Collection 的迭代器返回它们的顺序排列的。 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; } }
/** * 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. * * 将ArrayList的容量设置为当前size的大小,应用可使用此方法最小化实例的存储空间 * */ public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } }
/** * Increases the capacity of this <tt>ArrayList</tt> instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * 若有必要,增长此ArrayList实例的容量,以确保它至少能够容纳由minCapacity参数指定的元 * 素数。 * * @param minCapacity the desired minimum capacity */ 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); } } private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }
ensureCapacityInternal方法,数组容量检查,不够时则进行扩容,只供类内部使用,例如add(),addAll()等方法时会调用此方法进行容量检验,此时minCapacity 一般为size+napp
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code // 只有最小容量比当前容量大时才会进行扩容 if (minCapacity - elementData.length > 0) grow(minCapacity); } /** * 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 * * 最大存储容量 */ private static final int MAX_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 */ private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; // 先预先扩容1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) // 主要判断 预期最小容量 minCapacity 是否大于 MAX_ARRAY_SIZE newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
总结:dom
public boolean contains(Object o) { // 借用indexOf的方法看是否存在 return indexOf(o) >= 0; } // 实质就是遍历数组,使用Object的equals方法,返回-1为不存在此元素,lastIndexOf()方法就是反向遍历 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; } public boolean add(E e) { // 检验是否须要扩容 ensureCapacityInternal(size + 1); // Increments modCount!! // 先在index=size的位置赋值e,再将ArrayList的size增长一位 elementData[size++] = e; return true; } /** * 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} */ 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++; }
总结:ide
/** * 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); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); // 将数组最后一位 置 null,等待垃圾回收机制来回收 elementData[--size] = null; // clear to let GC do its work return oldValue; } public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } private class SubList extends AbstractList<E> implements RandomAccess {
ArrayList中的迭代器实现对AbstractList中的迭代器进行了优化源码分析
/** * Returns an iterator over the elements in this list in proper sequence. * * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>. * * 按原有list的顺序返回一个迭代器,遵循fail-fast机制。 * * * @return an iterator over the elements in this list in proper sequence */ public Iterator<E> iterator() { return new Itr(); } /** * An optimized version of AbstractList.Itr */ private class Itr implements Iterator<E> { // 后游标:指向下一个元素,等于下一个元素的索引值 int cursor; // index of next element to return // 前游标:指向当前元素,等于当前元素索引值,-1表明在最开始,还未指向元素 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的remove ArrayList.this.remove(lastRet); // remove以后 后游标左移 cursor = lastRet; // 重制前游标 lastRet = -1; // 而且会使预期修改次数 和 实际修改次数 保持相等 expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } // 检查 实际修改次数 和 预期修改次数是否相等 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
/** * Returns a list iterator over the elements in this list (in proper * sequence), starting at the specified position in the list. * The specified index indicates the first element that would be * returned by an initial call to {@link ListIterator#next next}. * An initial call to {@link ListIterator#previous previous} would * return the element with the specified index minus one. * * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. * * @throws IndexOutOfBoundsException {@inheritDoc} */ public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } /** * Returns a list iterator over the elements in this list (in proper * sequence). * * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. * * @see #listIterator(int) */ public ListIterator<E> listIterator() { return new ListItr(0); } /** * An optimized version of AbstractList.ListItr */ 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]; } 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 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; // add 操做会致使 modCount++,因此这边要保持相等 expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } }
remove和add操做成功后 lastRet都会从新赋值为-1,而且会执行expectedModCount = modCount操做,以防ConcurrentModificationException;优化
ListItr继承于Itr,增长了previous()等一些方法,最大不一样是游标cursor能够向前移动了。
注意:执行过next()方法后再执行previous(),当前元素并无改变(lastRet没有变),只是cursor进行了了改变,不要进行常规思考 previous()操做就是当前元素向前移动,next()就是当前元素向后移动,准确来讲是cursor进行先后移动,进行previous()操做时 lastRet始终等于cursor,next()操做时cursor始终比lastRet大1
源码版本为JDK1.8,只是对平常使用的基本操做的源码进行了分析,对于1.8的新特性并无涉及,等将主要集合类源码分析完后,会专门出一篇分析一下1.8中集合的新特性; 有建议或着问题的,请在文末留言,本人水平有限,有错误或理解误差,还请各位多多指导和见谅,如若转载,请代表出处;