1 扩容机制
1.1 源码分析
List<Integer> list = new ArrayList<>();
for (int i = 0;i < 15;i++){
list.add(i);
}
初始化:
// 默认初始化一个空的object数组
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
第一次添加:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
- 先检查容量
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
- 计算所需容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// private static final int DEFAULT_CAPACITY = 10;
// 默认初始化容量为10
// 对于空数组 需要比较所需当次所需容量是否大于10
// addAll()调用时,入参minCapacity可能大于10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
- 根据计算得到的所需容量决定是否扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
- 扩容
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
// 新容量 = 旧容量 + 旧容量 / 2 (位运算:右移相当于 / 2)
// 第一次添加时newCapacity计算得0
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
// newCapacity 第一次添加时会取minCapacity 即10
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 把旧数组复制到扩容后的新数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
- 最后完成添加操作
// 把待添加元素值 赋值在当前数组末位之后
elementData[size++] = e;
分析:
- 添加第一个元素所需容量为10,大于当前size即0,扩容为10
- 接着添加第2-10个元素不扩容 因为所需容量取了10
- 添加第11个元素 所需容量11,容量不够,扩容为原来的1.5倍
1.2 总结
对于一个空列表,第一次添加的时候,会扩容为10,容量大于10的时候扩容,会扩容为原来的1.5倍。
1.3 比较
Vector同样实现了List接口,不同的是它的很多方法都加了synchronized关键字,所以是线程安全的,而ArrayList不是线程安全的。Vector添加元素时初始容量为10,以后扩容为旧容量的2倍。