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 code
if (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 work
return 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
}