首先:我们知道ArrayList底层数据结构是数组
remove(int index)方法:
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);//将该元素下标加一的元素到数组的最后一个元素,复制到源数组中(从删除元素的下标开始复制,复制numMoved个)。
elementData[--size] = null; // clear to let GC do its work,最后将源数组中的最后一个元素赋值为空,让jvm的垃圾回收机制回收。
return oldValue;//返回删除的元素。
}
其中的rangeCheck是判断 index(即下标是否大于数组的大小)
由源码可以得当删除某元素后,该元素后的所有元素都会往前移动一位。所以,在for循环的循环体中删除了某个元素时要记得把下标-1,才是原本ArrayList中的下一个元素。
private void fastRemove(int index) {
modCount++;
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
}
我们也可以从源码中看到一个私有方法fastRemove,该方法和remove(int index)内容相似,少了关于index的检查判断,且其他非子类无法访问,因为这是remove(Object o)调用的方法,在remove(Object o)中已经判断了参数o是否该Arraylist中的元素,所以不需要判断,可以进行快速删除。值得一提的是,在remove(Object o)方法中也有删除ArrayList中为空的元素的代码:
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])) {
fastRemove(index);
return true;
}
}
return false;
}