我们知道数组是一种同类型的数据类型、连续的存储空间存储的结构,在分配内存空间的时候必须给定具体的数据size。所以我们一般在确定数据size的时候都会使用数组形式。其实ArrayList也是一种动态扩展的数组。ArrayList有这样一个构造函数public ArrayList(int initialCapacity),参数initialCapacity表示创建的时候分配的初始容量大小。然后我们看一下add的源码:
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
//确定容器大小
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
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);
}
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//oldCapacity >> 1右移一位,相当于oldCapacity /2,那么这句代码表示将容量扩展为原来的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:
//创建一个newCapacity容量的新数组,再把原数据拷贝进去(比较耗时的地方)
elementData = Arrays.copyOf(elementData, newCapacity);
}
前面我们说过,数组在内存中是连续分配的,所以非常适合需要随机访问数据的情况。比如,我们知道了a[0]的地址为1000,即base_address=1000,那么a[3]的地址=base_address+(3-0)*data_type_size (data_type_size为数据类型在内存中分配的大小,比如int类型数据,data_type_size就为4个字节)。所以数组的下标是从0开始,这样更方便计算,其实这个下标index可以理解为偏移量。