关于ArrayList的removeAll(batchRemove)方法解析

ArrayList的增加扩容啥的小伙伴一定很清楚了,那些也比较好理解,对于removeAll方法,大家想一想,以自己的思维去写一个removeAll方法,是怎样
写呢?

    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

这是jdk8给的removeall方法,我们只看参数,它接受的是一个实现了Collection接口的集合,意为从原有的list里,将传入的集合在list里含有的元素全部移除。
我试着自己想了一下,我很笨,我只要实现这个功能,根本不考虑时间复杂度,我就会把列表挨个遍历,拿到列表遍历的然后又拿去遍历集合,元素相等时,我就把此位置设为null,两层for循环,理解简单但是消耗大。
其实jdk的removeAll方法在遍历上差不多一样(本身contains方法就包含遍历)但是不同的是当元素存在相等时,对数据的处理,接下来我们上源码

    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;
    }

我们看下属性
elementData:list存放元素的数组
参数Collection<?> c:要去除的元素的集合
complement:一个参数,始终为false,先不用在意,在比较中起辅助作用
r,w则是遍历的下标
我们来看判断条件if (c.contains(elementData[r]) == complement),由于complement始终为false,所以这句话含义就为:
如果在要去除的元素的集合不含有当前list的数组r下标的元素,我们则进行if里面的操作,文字描述生疏,我们来图片展示一下
在这里插入图片描述

借用这位博主的一张图在这里插入图片描述

if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];

思路描述就是,在边进行判定的时候,边把数组的元素前移,
w这个下标,在c.contains为false时它才会自增,它并不代表的是重复元素的下标,而是在每次c.contains不成立时,标记这个位置,将r下标的某个元素移到此位置来,因为这时候就表明r下标的这个元素时不需要去除的,这样就形成了边判定边移动数组的行为。总有来说,只要有一个元素不符合,后面c.contains为true的时候,都会往前移动一个位置

                    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;
                    }

这部分
跟着上面的例子,w6,从原数组124679789的 下标6开始,将原数组大于下标6以后的数置null
modCount 修改的次数+3,原数组的长度修改为6。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值