ArrayList源码分析-删除

109 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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;
    }
  1. if (o == null) 如果要删除的值是 null,找到第一个值是 null 的删除
  2. for (int index = 0; index < size; index++) 如果要删除的值不为 null,找到第一个和要删除的值相等的删除
  3. 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
    }
  1. 首先仍然是modCount++,记录数组的结构发生变动

  2. numMoved 表示删除 index 位置的元素后,需要从 index 后移动多少个元素到前面去

  3. 减 1 的原因表示 size 从 1 开始算起,index 从 0开始算起

  4. System.arraycopy(elementData, index+1, elementData, index, numMoved)表示从 index +1 位置开始被拷贝,拷贝的起始位置是 index,长度是 numMoved

  5. elementData[--size] = null;数组最后一个位置赋值 null,帮助GC回收无用对象

  6. 从源码中,我们可以看出,某一个元素被删除后,为了维护数组结构,会把数组后面的元素往前移动

全部删除

    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;
    }
  1. 首先进行空检验
  2. 对原数据进行循环校验,如果包含了remove元素,则进行替换
  3. 根据情况进行数组拷贝/数据全set null
  4. 最后返回