我们通过源码来看一下add("白骨精")到底发生了什么
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }首先通过 ensureCapacityInternal(size + 1) 来保证底层Object[]数组有足够的空间存放添加的数据,然后将添加的数据存放到数组对应的位置上,我们看一下是怎么保证数组有足够的空间?
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }这里首先确定了Object[]足够存放添加数据的最小容量,然后通过 grow(int minCapacity) 来进行数组扩容
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; 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: elementData = Arrays.copyOf(elementData, newCapacity); }扩容规则为“数组当前足够的最小容量 + (数组当前足够的最小容量 / 2)”,即数组当前足够的最小容量 * 1.5,当然有最大值的限制。
因为最开始定义了集合容量为10,故而本次不会进行扩容,直接将第8个位置(从0开始,下标为7)设置为“白骨精”,这时Object[] elementData中数据如下:
还有和add()类似的方法。空间扩容原理都是一样,如:
add("铁扇", 0); //将数组中的元素各自往后移动一位,再将“铁扇”放到第一个位置上;
addAll(list..七个葫芦娃); //将集合{七个葫芦娃}放到"白骨精"后,很明显当前数组的容量已经不够,需要扩容了,不执行该句代码了;
addAll(list..哪吒三兄弟, 4);//从第五个位置将“哪吒三兄弟”插进去,那么数组第五个位置后的元素都需往后移动三位,数组按规则扩容为18。
指定了插入位置的,会通过rangeCheckForAdd(int index)方法判断是否数组越界
2. set(int index, E element)因为ArrayList底层是由数组实现的,set实现非常简单,调用 set(8, "猪八戒") 通过传入的数字下标找到对应的位置,替换其中的元素,前提也需要首先判断传入的数组下标是否越界。将“猕猴王”替换为“猪八戒”。
public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; }//返回值“猕猴王”,当前数组中数据:
3. get(int index)ArrayList中get方法也非常简单,通过下标查找即可,同时需要进行了类型转换,因为数组为Object[],前提是需要判断传入的数组下标是否越界。
public E get(int index) { rangeCheck(index); return elementData(index); } E elementData(int index) { return (E) elementData[index]; }调用get(6)返回”哪吒“。
4. remove(int index)