ArrayList部分源码了解(扩容、删除)--个人理解
ArrayList部分源码解释(扩容、删除)
扩容
ArrayList<Integer> list=new ArrayList<>();
int i=0;
while (i<=9){
list.add(i++);
}
list.add(2);
1、第一行进入构造函数(无参)
//有参构造函数,除了负数,initialCapacity多大就开辟多大的空间
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {//自定义容量不为0,如new ArrayList<>(11);
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {//自定义容量为0,如new ArrayList<>(0);
this.elementData = EMPTY_ELEMENTDATA;//传值为0
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//无参构造函数
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//对象实例化后list集合还是一个空集合
}
2、第四行进入添加元素(模拟第一次add操作,可知第一次添加操作后才会给集合一个10的容量)
public boolean add(E e) {
ensureCapacityInternal(size + 1); //1
elementData[size++] = e;//这里说明list集合的add方法就是往elementData数组中放元素
return true;
}
private void ensureCapacityInternal(int minCapacity) {//确定内部容量
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));//第一次此时minCapacity为10
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {//计算容量
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//判断当前elementData数组是否时null,如果是就将当前数组容量和默认容量10比较,一般第一次进来之后都会变成10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {//确保明确的容量
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)//当前所需容量minCapacity比实际容量大,必须进行扩容
grow(minCapacity);
}
private void grow(int minCapacity) {//扩容开始
// overflow-conscious code
int oldCapacity = elementData.length;//老数组为当前数组容量,第一次添加则为0
int newCapacity = oldCapacity + (oldCapacity >> 1);//进行1.5倍扩容,如果是第一次,newCapacity执行完为0
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:
elementData = Arrays.copyOf(elementData, newCapacity);//*** 这里是扩容的重点!!!!
}
当list集合是使用无参构造后第一次添加元素,先进入ensureCapacityInternal,此时minCapacity=1,进入后调用calculateCapacity方法,如果底层数组elementData是null,就把minCapacity和DEFAULT_CAPACITY(10)比较,比较完后minCapacity=10返回
进入ensureExplicitCapacity方法判断当前数组所需容量minCapacity是否大于实际容量,大于时进行扩容
3、第一次扩容完后,底层数组容量为10,第6行为添加10个元素后,现在模拟添加第11个元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); //11
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {//确定内部容量,minCapacity=11
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {//计算容量
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//第11次elementData为10,进不来
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;//直接返回minCapacity=11
}
private void ensureExplicitCapacity(int minCapacity) {//确保明确的容量
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)//当前所需容量minCapacity(11)比实际容量10大,必须进行扩容
grow(minCapacity);
}
private void grow(int minCapacity) {//扩容开始
// overflow-conscious code
int oldCapacity = elementData.length;//老数组为当前数组容量,第11次oldCapacity为10
int newCapacity = oldCapacity + (oldCapacity >> 1);//进行1.5倍扩容,扩容完之后newCapacity为15
if (newCapacity - minCapacity < 0)//准备扩容的值newCapacity比实际所需minCapacity的容量大,直接跳过
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)//这里是看当前所需容量是否超过数组最大的容量,一般不会超过
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);//*** 这里是扩容的重点!!!!
}
remover 删除
下标删除
//删除原理:数组复制
public E remove(int index) {
rangeCheck(index);//判断是否越界
modCount++;//统计修改次数
E oldValue = elementData(index);//保存下要删除的元素
int numMoved = size - index - 1;//统计要移动的元素个数
if (numMoved > 0)//数组元素前移
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;//返回删除的值
}
元素删除
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {//删除元素和列表的元素进行equals比较
fastRemove(index);
return true;
}
}
return false;
}