jdk源码阅读笔记之java集合框架(二)(ArrayList)
关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手。
ArrayList类定义:
public class ArrayList<E> extends AbstractList<E> implements List<E>
ArrayList基本属性:
/** * Default initial capacity.(默认初始化大小) */ private static final int DEFAULT_CAPACITY = 10; /** * Shared empty array instance used for empty instances. * 空数组,当调用无参数构造函数的时候默认给个空数组 */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * 真正存储数据的数组 */ private transient Object[] elementData; /** * The size of the ArrayList (the number of elements it contains). * 所存储数据的数量 */
ArrayList的add方法:
/** * Appends the specified element to the end of this list. * 插入数据,每一次都是从末尾插入 */ public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { if (elementData == EMPTY_ELEMENTDATA) { //此处表示若为空数组 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++;//jdk源码阅读笔记之java集合框架(三)(modCount) if (minCapacity - elementData.length > 0) /** * minCapacity=size+1 * 只用当数组实际存储元素数量+1大于数组长度是,需扩容 */ grow(minCapacity); } /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * 提高数组容量以确保至少能够存储minimum数量的数据 */ private void grow(int minCapacity) { int oldCapacity = elementData.length; //带符号右移等价于除以2,所以每一次扩容之后,数组的长度为原来的1.5倍。 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); }
ArrayList的remove方法:
remove方法分为 remove(Object o) 与 remove(int index)。俩方法类似,所以任挑其一进行分析。
/** * 移除指定下标的元素 */ public E remove(int index) { rangeCheck(index);//下标越界检查 modCount++; //"http://www.cnblogs.com/jw93/p/6845825.html"详细介绍 E oldValue = elementData(index); /** * 移除某一元素之后,需要将该元素后面的元素向前移动 * numMoved表示需要移动的元素个数 */ int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved);//此处为native方法 elementData[--size] = null; // clear to let GC do its work return oldValue; } /** * 下标越界检查 */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index));//抛出数组下标越界 } /** * 抛出异常时详细信息 */ private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; }