专栏首页强仔仔ArrayList之removeAll底层原理实现详解

ArrayList之removeAll底层原理实现详解

今天给大家介绍下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

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!
本文分享自作者个人站点/博客:http://blog.csdn.net/linzhiqiang0316复制
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • arraylist linkedlist底层实现原理[js底层原理]

    ArrayList的底层数据结构就是一个数组,数组元素的类型为Object类型,对ArrayList的所有操作底层都是基于数组的。

    Java架构师必看
  • ArrayList底层实现原理「建议收藏」

    ArrayList简介 ArrayList是我们开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是...

    全栈程序员站长
  • springcloud原理详解_数据库底层实现原理

    天天喊着微服务,微服务的,微服务怎么牛逼,微服务有多强大,学好微服务三天不用吃饭的那种?那我心里不禁一紧微服务到底是个啥?往下看!总有东西有点帮助!

    全栈程序员站长
  • MySQL 中 ACID 底层内部实现原理详解

    所谓事务是用户自定义的一个数据库操作序列,这些操作是一个不可分割的单位。我们要知道,事务 和 程序 是两个概念,一般来讲,一个程序中包含多个事务。

    八点半的Bruce、D
  • 深入详解Go的channel底层实现原理【图解】

    源码位于/runtime/chan.go中(目前版本:1.11)。结构体为hchan。

    sunsky
  • Java并发之底层实现原理学习笔记

    本篇博文将介绍java并发底层的实现原理,我们知道java实现的并发操作最后肯定是由我们的CPU完成的,中间经历了将java源码编译成.class文件,然后进行...

    MindMrWang
  • Java 泛型之 JDK 的底层实现原理

    Visit a TypeTree and produce a result of type T

    一个会写诗的程序员
  • JAVA-LOCK之底层实现原理(源码分析)

    首先和Synchronized(可以参考) 的不同之处,Lock完全用Java写成,在java这个层面是无关JVM实现的。其实现都依赖java.util.con...

    海涛
  • 面试必备之HashMap底层设计与实现详解

    这次主要是分析下HashMap的工作原理,为什么我会拿这个东西出来分析,原因很简单,以前我面试的时候,偶尔问起HashMap,99%的程序员都知道HashMap...

    java爱好者
  • 基础篇:详解锁原理,volatile+cas、synchronized的底层实现

    字节码出现了4: monitorenter和14: monitorexit两个指令;字面理解就是监视进入,监视退出。可以理解为代码块执行前的加锁,和退出同步时的...

    潜行前行
  • Spring Aop之Cglib实现原理详解

    Spring Aop实现对目标对象的代理,主要有两种方式:Jdk代理和Cglib代理。这两种代理的区别在于,Jdk代理与目标类都会实现同一个接口,并且在代理...

    田维常
  • Spring Aop之Jdk代理实现原理详解

    Jdk代理,也称为动态代理,其代理目标对象的方式是生成一个与目标对象实现同一个接口的类,该类的构造函数中会传入一个InvocationHandler类型的对象...

    田维常
  • Spring5.0源码深度解析之SpringBean声明事务底层实现原理

    将InfrastructureAdvisorAutoProxyCreator注入到IOC容器中:

    须臾之余
  • Java集合汇总篇「建议收藏」

    Java 集合框架一些列的接口和类来实现很多常见的数据结构和算法,例如 LinkedList 就是集合框架提供的实现了双向链表的数据结构,关于这一篇文章建议大家...

    全栈程序员站长
  • 动态代理之投鞭断流!看一下MyBatis的底层实现原理!

    一日小区漫步,我问朋友:Mybatis中声明一个interface接口,没有编写任何实现类,Mybatis就能返回接口实例,并调用接口方法返回数据库数据,你知道...

    Java后端技术
  • 动态代理之投鞭断流!看一下MyBatis的底层实现原理!

    一日小区漫步,我问朋友:Mybatis中声明一个interface接口,没有编写任何实现类,Mybatis就能返回接口实例,并调用接口方法返回数据库数据,你知道...

    用户5224393
  • 并发编程学习笔记03-Java并发机制的底层原理之原子操作的实现原理

    处理器会自动保证基本的内存操作的原子性。处理器保证从系统内存中读取或者写入一个字节是原子的,即:当一个处理器读取一个字节时,其他处理器不能访问这个字节的内存地址...

    WindCoder
  • Java集合详解1:一文读懂ArrayList,Vector与Stack使用方法和实现原理

    本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看

    Java技术江湖
  • Java并发机制的底层实现原理之volatile应用,初学者误看!

      Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制...

    爱撸猫的杰

扫码关注腾讯云开发者

领取腾讯云代金券