首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ArrayList之removeAll底层原理实现详解

ArrayList之removeAll底层原理实现详解

作者头像
林老师带你学编程
发布2019-07-02 10:29:24
1.8K0
发布2019-07-02 10:29:24
举报
文章被收录于专栏:强仔仔强仔仔

今天给大家介绍下ArrayList之removeAll的用法,并深入讲解一下它的底层实现原理。

大家先看如下所示代码:

        CollectionTest collectionTest =new CollectionTest();
        List<DataDto> list1 =new ArrayList<>();
        for(int i=1;i<=10;i++){
            DataDto dataDto =new DataDto(i+"");
            list1.add(dataDto);
        }
        List<DataDto> list2 =new ArrayList<>();
        DataDto dataDto1 =new DataDto("2");
        list2.add(dataDto1);
        list1.removeAll(list2);
        collectionTest.print(list1);

不知道大家猜到结果了没,结果就是DataDto(“2”)并没有被移除掉,我们将list1集合打印出来,显示集合没有任何一个元素被删除。

1
2
3
4
5
6
7
8
9
10

下面我们再看看下面这个案例代码:

        CollectionTest collectionTest =new CollectionTest();
        List<DataDto> list1 =new ArrayList<>();
        for(int i=1;i<=10;i++){
            DataDto dataDto =new DataDto(i+"");
            list1.add(dataDto);
        }
        List<DataDto> list2 =list1.subList(0,2);
        list1.removeAll(list2);
        collectionTest.print(list1);

这个情况下,removeAll成功的将1、2两个元素移除掉了。结果如下所示:

3
4
5
6
7
8
9
10

这到底是什么情况呢,为什么发生这种情况呢?莫着急,我们看一下removeAll底层的源码是如何实现的。ArrayList底层源码如下所示:

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

第一步:

先判断要移除的集合是否为null,如果为null则抛出null异常。

第二步:

如果不为null,则接着调用batchRemove方法即可移除成功。

代码的原理可以简单概述为如下过程:

  1. 通过contains方法,将所有不需要移除的元素放入elementData中,然后标记最后一个放入元素的位置w。
  2. 将所有需要移除的元素设置为null。
  3. 将size的大小设置为w。
  4. 修改modCount字段(该字段主要是为了防止多线程模式下安全问题)。
  5. 最后返回移除成功的标识。

备注:

System.arraycopy主要作用是为了防止contains出现异常,导致集合出现问题。

从源码可以看出,上面案例一之所以移除不成功的原因是因为:contains底层是通过equals实现的,所以对比的是元素的堆地址。而案例一的移除对象是新new出来的,所以不是同一个地址,所以也当然移除不了。

源码就分析到这边了,原理其实很简单。平时大家在写业务代码的时候,一定要抽空去了解代码背后的实现原理,这样才能深入的成长。

林老师带你学编程https://wolzq.com

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年06月23日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档