ArrayList是工作中常用的集合, 基于数组实现, 可以插入空数据, 也支持随机访问. ArrayList比较适合 get/set操作, 因为 add/remove需要移动数据, 相对来说比较消耗性能.
默认初始长度
1.默认初始长度为 10
2.底层结构为Object[] 数组
private static final int DEFAULT_CAPACITY = 10;private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};/*** 构造一个初始容量为10的空列表*/public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
添加方法 add()
向数组中添加元素, 流程如下
/*** 将指定的元素追加到此列表的末尾.*/public boolean add(E e) {// 扩容ensureCapacityInternal(size + 1); // Increments modCount!!// 添加元素elementData[size++] = e;return true;}
2.扩容过程
transient Object[] elementData;// 扩容private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}// 计算容量, elementData为空 则使用默认容量 10, 指定容量private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}// 修改次数自增, 并且如果 新的长度-原长度>0 则使用 grow(minCapacity)方法进行扩容private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);}
添加元素赋值
elementData[size++] = e;
扩容流程 grow(minCapacity)
通过扩容流程可以看出扩容过程中, 是将创建一个原数组1.5倍大小的新数组, 同时将数组元素复制到新数组, 所以一般使用中, 尽量指定数组大小, 从而避免数组的复制.
/*** 增加容量确保能容纳 minCapacity 数量的元素*/private void grow(int minCapacity) {// overflow-conscious code// 获取当前 elementData 的长度int oldCapacity = elementData.length;// 获取新的长度 为当前长度的 1.5倍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);}
删除 remove 方法
删除过程中使用 System.arraycopy 本地方法, 对数组进行复制, 所以 ArrayList的 新增和删除方法性能不如, LinkList, 但是 get和set方法, 则直接根据索引修改数据, 比较适合对数据进行修改的操作.
/*** 删除指定位置的元素, 后面的元素将前移*/public E remove(int index) {// 检查索引 否则抛出 IndexOutOfBoundsException(outOfBoundsMsg(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 workreturn oldValue;}/*** 删除指定元素*/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;}/*** System.arraycopy 方法拷贝 删除*/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; // clear to let GC do its work}
