Java集合框架 03.深入ArrayList源码
前置知识
数据结构
- 数组
java
- 数组
正文
ArrayList是基于动态数组实现的,对象内部存在一个Object数组elementData。
transient Object[] elementData;
- 可以随机访问,按照索引位置进行访问效率很高,用算法描述中的术语,效率是O(1)。
- 除非数组已排序,否则按照内容查找元素效率比较低,具体是O(N), N为数组内容长度,也就是说,性能与数组长度成正比。
- 添加元素的效率还可以,重新分配和复制数组的开销被平摊了,具体来说,添加N个元素的效率为O(N)。
- 插入和删除元素的效率比较低,因为需要移动元素,具体为O(N)。
elementData初始化与扩容
ArrayList在新增元素的时候,会判断elementData数组大小是否能存下。这个方法便是void ensureCapacityInternal(int minCapacity)
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//判断elementData == {},等价于判断ArrayList实例是否未初始化。
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//确保初始化长度最小为10。
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
//修改计数+1,相关知识见Iterable。
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
java7中elementData默认会初始化为长度为10的数组。java8中做了修改,只有在第一次插入的时候才会进行实际的初始化。
private void grow(int minCapacity) {
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);
}
扩容函数中的核心就是进行1.5倍扩容elementData数组。