·new ArrayList();
// 初始化ArrayList实例,则elementData={}
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
}
transient Object[] elementData;
由此可见底层使用的是一个数组
·add(E e)
流程:先确定是否需要扩容,需要扩容则扩容至原大小+原大小右移1位,默认的容量为10,所以在10以下都不需要扩容,如果计算出来的新容量仍不能满足最小扩容量,新容量取最小扩容量,如果新容量大于Integer.MAX_VALUE - 8,则取integer的最大值0x7fffffff
public boolean add(E e) {
// 确定是否需要扩容,如果需要,则进行扩容操作
ensureCapacityInternal(size + 1); // Increments modCount!!
//size=0,elementData[0]="a1",然后a自增为1
elementData[size++] = e;
return true;
}
1.ensureCapacityInternal,size为当前容器的大小,当前为第一次调用,所以size为0
// ArrayList中包含的元素数量
private int size;
2.calculateCapacity,第一次调用,此时elementData是一个空数组,minCapacity是1
// 第一次新增元素,所以size=0,则:minCapacity=size+1=1
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
3.判断传入的elementData是否是空数组,是的话计算最小容量,并返回,第一次传入的数组是空数组,所以判断大小后返回了DEFAULT_CAPACITY=10,返回步骤2
// 第一次新增元素,elementData={} minCapacity=1
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//ArrayList默认的容量为10个Object元素
private static final int DEFAULT_CAPACITY = 10;
4.第一次新增元素,因为计算得到的minCapacity为10,当前数组的容量为0,所以需要调用grow方法进行扩容
//第一次新增元素,minCapacity=10
private void ensureExplicitCapacity(int minCapacity) {
//modCount++后,modCount=1
modCount++;
//如果所需的最小容量大于elementData数组的容量,则进行扩容操作
if (minCapacity - elementData.length > 0) { //10-0=10,满足扩容需求
//minCapacity=10
grow(minCapacity);
}
}
5.进行扩容操作
private void grow(int minCapacity) {
// 保存原有数组elementData的长度 oldCapacity=0
int oldCapacity = elementData.length;
// 右移一位表示除2,所以新增oldCapacity的一半整数长度作为newCapacity的额外增长长度
int newCapacity = oldCapacity + (oldCapacity >> 1); //newCapacity=0+(0>>1)=0
// 新的长度newCapacity依然无法满足需要的最小扩容量minCapacity,则新的扩容长度为minCapacity
if (newCapacity - minCapacity < 0) {
// newCapacity=10
newCapacity = minCapacity;
}
// 新的扩容长度newCapacity超出了最大的数组长度MAX_ARRAY_SIZE
if (newCapacity - MAX_ARRAY_SIZE > 0) {
newCapacity = hugeCapacity(minCapacity);
}
// 扩展数组长度为newCapacity,并且将旧数组中的元素赋值到新的数组中 newCapacity=10, 扩容elementData的length=10
elementData = Arrays.copyOf(elementData, newCapacity);
}
·remove(int index)
public E remove(int index) {
// 校验传入的参数index是否超出了数组的最大下标,如果超出,则抛出:IndexOutOfBoundsException异常
rangeCheck(index);
// 集合的修改次数加1
modCount++;
// 获得index下标对应的旧值oldValue
E oldValue = elementData(index);
// 获得需要移动元素的个数
int numMoved = size - index - 1;
if (numMoved > 0) {
/**
* {"a1","a2","a3","a4"}
* 假设删除"a2",那么index=1, numMoved=2, 那么下面的语句执行的就是:
* 将第一个入参的elementData从第2位"a3"(index+1)开始复制2位(numMoved)即:"a3","a4";
* 复制到第三个入参elementData的第1位(index),即elementData变成 {"a1","a3","a4","a4"}
*/
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
}
// 通知jvm将之前的最后一位元素进行垃圾回收
elementData[--size] = null; // clear to let GC do its work
// 返回已被删除的元素
return oldValue;
}
·clear()
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++) {
elementData[i] = null;
}
size = 0;
}
·get(int index)
public E get(int index) {
// 检查是否越界
rangeCheck(index);
return elementData(index);
}
·set(int index, E element)
public E set(int index, E element) {
// 判断index是否超出了ArrayList中包含的元素数量,如果超出,则抛出IndexOutOfBoundsException异常
rangeCheck(index);
// 获得index下标对应的旧值
E oldValue = elementData(index);
// 将index下标对应的值,赋值为新值——element
elementData[index] = element;
// 返回index下标对应的旧值
return oldValue;
}
·add(int index, E element)
public void add(int index, E element) {
rangeCheckForAdd(index); // 检查是否越界
ensureCapacityInternal(size + 1); // Increments modCount!!
/**
* {"a1","a2","a3","a4"}
* 调用add(1,"a8");
* 此时参数是(e,1,e,2,3);
* 将第一个e的第1个元素开始,复制3个元素,即{"a2","a3","a4"}到第二个e的第2位开始的后3位元素,即{"a1","a2","a2","a3","a4"}
* 因为前面已经判断过扩容,所以此处不会越界
*/
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
**************此文章只是本人学习过程中的学习笔记,不做其他用途,如果有其他意见,欢迎一起讨论,谢谢,侵删*************************