ArrayList流程图
ArrayList源码
step1:new ArrayList();
初始化ArrayList实例,elementData={}
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
* 初始化的空数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
step2:list.add(”a1“);
新增元素
/**
*The size of the ArrayList (the number of elements it contains).
*ArrayList中包含的元素数量
*/
private int size;
/**
* Default initial capacity.
* 默认容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 记录着集合的修改次数,就是每次add或者remove后,modCount的值会加1
* ArrayList是非线程安全的,在使用迭代器遍历的时候,用来检查列表中的元素是否发生结构性变化时需要使用,防止一个线程正在迭代遍历,另一个线程修改了这个列表的结构
*/
protected transient int modCount = 0;
/**
* Appends the specified element to the end of this list.
* 新增元素操作
*/
public boolean add(E e) {
//确定是否需要扩容,如果需要则进行扩容操作
//第一次添加操作时,size=0
ensureCapacityInternal(size + 1);
//对下标为size的数组位置赋值,同时将下标移动到下一个
elementData[size++] = e;
return true;
}
//设置容量,第一次新增元素时minCapacity=1
private void ensureCapacityInternal(int minCapacity) {
//第一次新增元素,calculateCapacity方法返回值为DEFAULT_CAPACITY,10
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/**
* 如果elementData数组中没有已存储的元素,则返回默认值10
* 否则,返回miniCapacity
* @param elementData 底层存储ArrayList元素的数组
* @param minCapacity ArrayList中的元素个数
*/
//第一次新增元素时,elementData={},minCapacity=1
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//DEFAULT_CAPACITY=10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
/**
* 确保明确的ArrayList的容量
* @param minCapacity ArrayList所需的最小容量
*
* 第一次新增元素,minCapacity=10
*/
private void ensureExplicitCapacity(int minCapacity) {
//修改次数,从0开始
modCount++;
// overflow-conscious code
//如果所需的最小容量大于elementData数组的容量,则进行扩容操作
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 扩容操作
* @param minCapacity 所需要的最小扩容量
*
* 第一次新增元素,minCapacity=10,即:需要将elementData为0的长度扩容为10长度
*/
private void grow(int minCapacity) {
// 原有数组elementData的程度
int oldCapacity = elementData.length;
//A>>1 等于 A/2
//A<<1 等于 A*2
//新增oldCapacity的一半整数长度作为newCapacity
int newCapacity = oldCapacity + (oldCapacity >> 1);
//新的长度newCapacity依然无法满足需要的最小扩容量minCapacity,则新的扩容长度为minCapacity
if (newCapacity - minCapacity < 0){
newCapacity = minCapacity;
}
//校验新的扩容长度newCapacity是否超过最大限制,MAX_ARRAY_SIZE=Integer.MAX_VALUE - 8;
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);
}
step3:list.set(0,obj);
修改元素
/**
* Replaces the element at the specified position in this list with
* the specified element.
*
* @param index index of the element to replace 需要替换的元素下标
* @param element element to be stored at the specified position 新的值
* @return the element previously at the specified position 被替换的值
*/
public E set(int index, E element) {
//校验下标是否越界
rangeCheck(index);
//获取下标为index的元素的旧值
E oldValue = elementData(index);
//将新值设置的下标index位置
elementData[index] = element;
return oldValue;
}
/**
*校验下标是否越界
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
setp4:list.get(index)
读取元素
/**
* Returns the element at the specified position in this list.
*
*/
public E get(int index) {
//校验下标index是否越界
rangeCheck(index);
//返回下标index的值
return elementData(index);
}
setp5:list.remove(index)
删除元素
/**
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices).
*
* 删除元素
*/
public E remove(int index) {
//校验下标index是否越界
rangeCheck(index);
//记录异常修改
modCount++;
//获取下标index的值
E oldValue = elementData(index);
//需要移动的长度
int numMoved = size - index - 1;
if (numMoved > 0)
//从需要删除的index后一位开始到末尾的这部分数据,整体都向前移动一个元素
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//通知jvm将之前的最后一位元素进行垃圾回收,同时将数组长度size减1
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}