ArrayList类中一共给出了两种remove方法,下面来对这两种方法详解:
时隔一年,再看这篇博客。(当时写的真垃圾,重新读了源码之后)下面将重写一波。
参数为元素下标(int型),详解请看代码注释
总得来说就是,先判断是否越界,然后取出值。如果被删除的不是最后一个元素,那么将调用一个本地方法把数组向前移动一位,原理就是把被删除元素后面的所有元素从被删除元素位置开始复制到原数组中。
// 参数是下标
// 返回值是被删除的元素值
public E remove(int index) {
// 首先检查下标是否越界,rangeCheck(index)是个内部私有方法,如果下标越界,将抛出异常
rangeCheck(index);
// 当前列表的修改次数加1
// 这个参数是用于迭代器fail-fast机制的
// 当在遍历列表时,如果对列表进行删除操作时,将会抛出异常
modCount++;
// 根据下标获取对应的值
E oldValue = elementData(index);
// 计算要删除位置的元素后还有几个元素,用于后面的操作
int numMoved = size - index - 1;
// 如果要删除的元素不是最后一个元素
if (numMoved > 0)
// 这是jdk的一个本地方法,用于将一个数组从指定位置复制到目标数组的指定位置
// 其中numMoved就是要复制的个数,也就是被删除元素后面的元素个数
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 把列表大小减1,并把最后一个元素置空,让垃圾收集器把它回收
// 这里如果不置空,它将会保存着一个引用,那么垃圾收集器将无法回收它,可能会造成内存泄漏
elementData[--size] = null; // clear to let GC do its work
// 将被删除的值返回
return oldValue;
}
参数为对象
如果上面的方法理解了,这个方法就很容易了。这个方法应该是indexOf(Object o)和remove(int index)的结合体。先查找到指定对象,再根据下标来删除对应的元素。但这里调用得并不是remove(int index),而是调用了另一个私有方法,下面将贴出源码,分析其不同之处。
- remove(Object o)
// 参数是对象
// 返回值为是否删除成功
public boolean remove(Object o) {
// 如果对象为空(ArrayList允许元素为空)
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;
}
- fastRemove(int index)
私有删除方法,跳过边界检查并且不返回删除元素值(这就是不同之处,会提高的一定的效率)
因为这里的index是根据元素得出的,所以不可能越界
这里也不需要返回值,因为在上面的方法中只需返回是否成功
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
}