ArrayList的结构
ArrayList的结构是一个数组
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
* ArrayList的存储结构是个数组,容量是数组的长度,
* 空数组指向静态的默认的空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA,
* 当添加一个元素的时候,就会指向默认大小的数组了DEFAULT_CAPACITY
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* 默认初始化容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 默认空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 默认空数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 扩容次数
protected transient int modCount = 0;
1. ArrayList如何存储一个元素?
// 添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保数组的容量>(当前元素个数+1)
elementData[size++] = e; //将要添加的元素放到对应位置上
return true;
}
2.如何确保数组的大小 > 当前元素个数+1 ?
当如果添加元素后的个数 > 当前数组的长度,则对数组进行扩容
// 确保数组的容量
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// 计算容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 添加第一个元素,返回默认大小
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 如果添加元素后的个数 > 当前数组的长度,则对数组进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
3.如何进行扩容
private void grow(int minCapacity) {
// oldCapacity 旧的数组的长度
int oldCapacity = elementData.length;
// newCapacity 新的数组的长度 = 旧的数组的长度+旧的数组的长度/2
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果扩容后的新的数组的长度 < 元素的个数,则新的数组长度 = 元素的个数
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果扩容后的新的数组的长度 < 最大的数组长度,则新的数组长度
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 将旧的数组元素放到新的数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}
4.如何取一个元素?
按照索引读取即可
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
网友评论