一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
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;
}
if (o == null)如果要删除的值是 null,找到第一个值是 null 的删除for (int index = 0; index < size; index++)如果要删除的值不为 null,找到第一个和要删除的值相等的删除if(o.equals(elementData[index])这里是根据 equals 来判断值相等的,相等后再根据索引位置进行删除
根据索引位置进行元素的删除:
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
}
-
首先仍然是
modCount++,记录数组的结构发生变动 -
numMoved表示删除 index 位置的元素后,需要从 index 后移动多少个元素到前面去 -
减 1 的原因表示 size 从 1 开始算起,index 从 0开始算起
-
System.arraycopy(elementData, index+1, elementData, index, numMoved)表示从index +1位置开始被拷贝,拷贝的起始位置是 index,长度是 numMoved -
elementData[--size] = null;数组最后一个位置赋值 null,帮助GC回收无用对象 -
从源码中,我们可以看出,某一个元素被删除后,为了维护数组结构,会把数组后面的元素往前移动
全部删除
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
- 首先进行空检验
- 对原数据进行循环校验,如果包含了remove元素,则进行替换
- 根据情况进行数组拷贝/数据全set null
- 最后返回