Java中ArrayList的removeAll方法详解

发布时间 - 2026-01-11 02:09:57    点击率:

本文介绍的是关于Java中ArrayList的removeAll方法的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍:

在开发过程中,遇到一个情况,就是从所有骑手Id中过滤没有标签的骑手Id(直接查询没有标签的骑手不容易实现),

List<Integer> allRiderIdList = new ArrayList(); // 所有的骑手,大致有23W数据
List<Integer> hasAnyTagRiderId = new ArrayList(); // 有标签的骑手, 大致有21W数据
List<Integer> withoutAnyTagRiderList = allRiderIdList.removeAll(hasAnyTagRiderId);

逻辑很简单,就是取一个差集,这样子就拿到没有任何标签的骑手数据。

但是在实际开发过程中,removeAll这个动作很耗时,做测试大概要4分钟左右。查看ArrayList中removeAll的源码片段:

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++) // 循环原来的list
  if (c.contains(elementData[r]) complement) // 这里调用contains方法
  elementData[w++] = elementData[r];
 } finally {
 ....
 }
 return modified;
}

在循环过程中调用contains方法做比较,查一下ArrayList的contains方法,源代码片段如下:

public boolean contains(Object o) {
 return indexOf(o) >= 0;
}

public int indexOf(Object o) {
 if (o null) {
 for (int i = 0; i < size; i++)
  if (elementData[i]==null)
  return i;
 } else {
 for (int i = 0; i < size; i++)
  if (o.equals(elementData[i]))
  return i;
 }
 return -1;
}

这可以看出来,在比较的过程中,又调用了一次循环。

所以removeAll两层for循环,复杂度O(m*n),所以在操作比较大的ArrayList时,这种方法是绝对不可取的。

下面看一下最终的实现方式:

private List<Integer> removeAll(List<Integer> src, List<Integer> target) {
 LinkedList<Integer> result = new LinkedList<>(src); //大集合用linkedlist
 HashSet<Integer> targetHash = new HashSet<>(target); //小集合用hashset
 Iterator<Integer> iter = result.iterator(); //采用Iterator迭代器进行数据的操作

 while(iter.hasNext()){ 
 if(targetHash.contains(iter.next())){
  iter.remove();
 }
 }
 return result;
}

同样数量级list, 整个过程只需要几十毫秒,简直天壤之别。

回过头来,比较一下两种实现方式,为什么差距这个大。

1、外层循环

     一个是普通的for循环,一个迭代器遍历元素,二者相差不大

2、内层数据比较

     前者通过index方法把整个数组顺序遍历了一遍;

     后者调用HashSet的contains方法,实际上是调用HashMap的containKey方法,查找时是通过hash表查找,复杂度为O(1)。

接下来我们简单看一下hash表。

hash表是一种特殊的数据结构,它同数组、链表以及二叉排序树等相比较有很明显的区别,它能够快速定位到想要查找的记录,而不是与表中存在的记录的关键字进行比较来进行查找。这个源于Hash表设计的特殊性,它采用了函数映射的思想将记录的存储位置与记录的关键字关联起来,从而能够很快速地进行查找。可以简单理解为,以空间换时间,牺牲空间复杂度来换取时间复杂度。

hash表采用一个映射函数 f : key —> address 将关键字映射到该记录在表中的存储位置,从而在想要查找该记录时,可以直接根据关键字和映射关系计算出该记录在表中的存储位置,通常情况下,这种映射关系称作为hash函数,而通过hash函数和关键字计算出来的存储位置(注意这里的存储位置只是表中的存储位置,并不是实际的物理地址)称作为hash地址。

上面的图大家应该都很熟悉,hash表的一种实现方式,是由数组+链表组成的。元素放入hash表的位置通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。

另外hash表大小的确定也很关键,如果hash表的空间远远大于最后实际存储的记录个数,则造成了很大的空间浪费,如果选取小了的话,则容易造成冲突。在实际情况中,一般需要根据最终记录存储个数和关键字的分布特点来确定Hash表的大小。还有一种情况时可能事先不知道最终需要存储的记录个数,则需要动态维护Hash表的容量,此时可能需要重新计算Hash地址。
当然,关于hash表要说的话太多,先简单到此吧~~~

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。


# arraylist  # removeall  # arraylist的removeall  # java  # removeall方法  # JAVA ArrayList详细介绍(示例)  # JAVA LinkedList和ArrayList的使用及性能分析  # Java中ArrayList类的使用方法  # java的arraylist排序示例(arraylist用法)  # Java ArrayList 数组之间相互转换  # java数据结构实现顺序表示例  # Java实现一个顺序表的完整代码  # Java实现顺序表的增删查改功能  # Java中ArrayList与顺序表的概念与使用实例  # 过程中  # 遍历  # 小集  # 看一下  # 的是  # 链表  # 迭代  # 是一种  # 太多  # 相关内容  # 是由  # 在实际  # 没有任何  # 两种  # 而在  # 是从  # 一遍  # 数据结构  # 也很  # 不容易 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 成都网站制作公司哪家好,四川省职工服务网是做什么用?  详解vue.js组件化开发实践  如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程  Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】  如何用虚拟主机快速搭建网站?详细步骤解析  移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?  企业网站制作这些问题要关注  如何选择可靠的免备案建站服务器?  公司网站制作价格怎么算,公司办个官网需要多少钱?  如何在 Telegram Web View(iOS)中防止键盘遮挡底部输入框  JS中页面与页面之间超链接跳转中文乱码问题的解决办法  简历在线制作网站免费版,如何创建个人简历?  如何使用 jQuery 正确渲染 Instagram 风格的标签列表  Win11怎么设置默认图片查看器_Windows11照片应用关联设置  JavaScript模板引擎Template.js使用详解  如何快速启动建站代理加盟业务?  Android自定义控件实现温度旋转按钮效果  laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法  微信小程序 input输入框控件详解及实例(多种示例)  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全  如何用花生壳三步快速搭建专属网站?  Laravel如何处理文件下载请求?(Response示例)  Windows10如何更改计算机工作组_Win10系统属性修改Workgroup  Android GridView 滑动条设置一直显示状态(推荐)  Laravel怎么返回JSON格式数据_Laravel API资源Response响应格式化【技巧】  香港服务器网站推广:SEO优化与外贸独立站搭建策略  Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】  如何撰写建站申请书?关键要点有哪些?  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  Android中AutoCompleteTextView自动提示  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  如何在Ubuntu系统下快速搭建WordPress个人网站?  如何挑选最适合建站的高性能VPS主机?  Laravel如何实现文件上传和存储?(本地与S3配置)  高性能网站服务器部署指南:稳定运行与安全配置优化方案  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  微信小程序 scroll-view组件实现列表页实例代码  Laravel如何清理系统缓存命令_Laravel清除路由配置及视图缓存的方法【总结】  Mybatis 中的insertOrUpdate操作  lovemo网页版地址 lovemo官网手机登录  Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程  Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧  Laravel怎么解决跨域问题_Laravel配置CORS跨域访问  清除minerd进程的简单方法  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  Laravel如何创建和注册中间件_Laravel中间件编写与应用流程  Laravel如何处理和验证JSON类型的数据库字段  海南网站制作公司有哪些,海口网是哪家的?