arraylist源码解析
arrayList是线性表的一种具体实现,底层使用数组存储数据的。
类关系结构
]
关键属性
//默认初始化容量
private static final int DEFAULT_CAPACITY = 10;
//默认为空时的数组
private static final Object[] EMPTY_ELEMENTDATA = new Object[0];
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];
//存放数据的数组
transient Object[] elementData;
//数组已存放元素个数
private int size;
//最大数组长度
private static final int MAX_ARRAY_SIZE = 2147483639;
构造函数解析
初始化容量
public ArrayList(int initialCapacity) {
//如果initialCapacity大于0,初始化数组;
//如果initialCapacity小于0,抛出异常;
//initialCapacity等于0,初始化一个空数组;
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else {
if (initialCapacity != 0) {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
this.elementData = EMPTY_ELEMENTDATA;
}
}
关键函数解析
- add(E e)
public boolean add(E e) {
//判断如果数组长度不够,就需要扩容
this.ensureCapacityInternal(this.size + 1);
//在数组的最后以为存放值
this.elementData[this.size++] = e;
return true;
}
private void ensureExplicitCapacity(int minCapacity) {
//minCapacity:存入元素需要的数组的最小容量
//this.elementData.length:数组长度
++this.modCount;
//如果存入元素需要的数组的最小长度大于数组的长度,那么数组需要扩容
if (minCapacity - this.elementData.length > 0) {
this.grow(minCapacity);
}
}
private void grow(int minCapacity) {
//数组长度
int oldCapacity = this.elementData.length;
//数组扩容后的长度,理论上是原数组长度的三倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
//防止以为运算出现负值
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
if (newCapacity - 2147483639 > 0) {
newCapacity = hugeCapacity(minCapacity);
}
//数组复制
this.elementData = Arrays.copyOf(this.elementData, newCapacity);
}
- add(int index, E element)
public void add(int index, E element) {
//检查数组下标是否越界
this.rangeCheckForAdd(index);
//确定是否需要扩容
this.ensureCapacityInternal(this.size + 1);
//把this.elementData这个数组里下标从index开始,
后面( this.size - index)位,往后移一位
System.arraycopy(this.elementData, index, this.elementData, index + 1, this.size - index);
//在下标位index的地方放入元素
this.elementData[index] = element;
++this.size;
}
- remove(int index)
public E remove(int index) {
//检查数组下标是否越界
this.rangeCheck(index);
++this.modCount;
//缓存index下标的旧值
E oldValue = this.elementData(index);
//计算数组中待移动的长度
int numMoved = this.size - index - 1;
if (numMoved > 0) {
//把数组中index之后的元素向前移以为
System.arraycopy(this.elementData, index + 1, this.elementData, index, numMoved);
}
//数组中最后以为元素置空
this.elementData[--this.size] = null;
return oldValue;
}