List的remove()方法详解
一、错误使用场景
1、普通for循环遍历List删除指定元素,list.remove(index)
示例:将姓张的名字移除掉
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六")); nameList.add("张七"); nameList.add("张八"); for (int i = 0; i < nameList.size(); i++) {String name = nameList.get(i);System.out.println("当前遍历对象==="+name);if (name.startsWith("张")) {nameList.remove(i);} } System.out.println(nameList);
输出结果:
【李四】【张八】遍历被跳过,【张八】没有被成功移除
原因分析:
List调用remove(index)方法后,会移除index位置上的元素,之后的所有元素依次前移,当移除完【张三】时,【李四】变成了数组的第一位,此时的索引应该要index-1才能获取到【李四】。所以每移除一个元素时就需要把index-1,否则原来索引为index+1的元素就无法遍历到。
2、foreach遍历List删除元素
示例:同上
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六")); nameList.add("张七"); nameList.add("张八"); for (String name : nameList) {System.out.println("当前遍历对象==="+name);if (name.startsWith("张")) {nameList.remove(name);} } System.out.println(nameList);
输出结果:
原因分析:
foreach循环实际上是迭代,使用list.remove(item)方法后,list 对象的modCount值进行了修改,而 list对象的迭代器中的expectedModCount值没有修改,所以抛出了异常
3、直接使用list.remove(object)
示例: 将张三从数组中移除
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六")); nameList.add("张三"); nameList.add("张三"); nameList.remove("张三"); System.out.println(nameList);
输出结果:[李四, 王五, 赵六, 张三, 张三]
原因分析:
list.remove(object)的逻辑和list.remove(index)大致相同:元素依次遍历,数组中存在与入参对象相等的元素就移除,之后的所有元素依次前移,返回true,若不存在与入参相等的元素,返回false。
二、正确使用方法
1、 使用list.removeIf()方法
removeIf()的入参是一个过滤条件,用来判断需要移除的元素是否满足条件。
原理:方法中设置了一个removeSet,把满足条件的元素索引坐标都放入removeSet,然后统一对removeSet中的索引进行移除
示例:将姓张的名字移除掉
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六")); nameList.add("张七"); nameList.add("张八"); nameList.removeIf(o->o.startsWith("张")); System.out.println(nameList);
输出结果:[李四, 王五, 赵六]
2、使用迭代器Iterator移除元素
迭代器是一个链表,直接使用remove操作不会出现问题
示例:同上
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六")); nameList.add("张七"); nameList.add("张八"); Iterator<String> iterator = nameList.iterator(); while (iterator.hasNext()) {if (iterator.next().startsWith("张")) {iterator.remove();} } System.out.println(nameList);
输出结果:[李四, 王五, 赵六]
3、使用list.removeAll()方法
定义一个需要移除的数组,for循环内将需要移除的元素收集在定义的数组中,for循环结束后直接removeAll()
示例:同上
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六")); nameList.add("张七"); nameList.add("张八"); List<String> removeList = new ArrayList<>(); for (String name : nameList) {if (name.startsWith("张")) {removeList.add(name);} } nameList.removeAll(removeList); System.out.println(nameList);
输出结果:[李四, 王五, 赵六]
4、倒序遍历元素然后删除
正序删除元素会移位那我们转变思维倒序遍历
示例:
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六")); nameList.add("张七"); nameList.add("张八"); for (int i = nameList.size() - 1; i >= 0; i--) {String name = nameList.get(i);System.out.println("当前遍历对象===" + name);if (name.startsWith("张")) {nameList.remove(i);} } System.out.println(nameList);
输出结果:
三、总结
1、使用普通for循环删除元素时需要注意索引会变化的问题
2、list删除元素时建议使用迭代器Iterator或者removeIf()方法
List的remove()方法详解相关推荐
- java的remove iterator_Java集合 iterator.remove()方法详解
直接上代码: public classtest {public static voidmain(String[] args) { List list = new ArrayList<>() ...
- 序列内置方法详解(string/list/tuple)
一.常用方法集合 1.1.string,字符串常用方法 以下举例是python2.7测试: 函数名称 作用 举例 str.capitalize() 字符串第一个字符如果是字母,则把字母替换为大写字母. ...
- ASP.NET MVC 5 学习教程:Details 和 Delete 方法详解
ASP.NET MVC 5 学习教程:Details 和 Delete 方法详解 原文 ASP.NET MVC 5 学习教程:Details 和 Delete 方法详解 在教程的这一部分,我们将研究一 ...
- python列表的内置方法_Python内置方法详解
1. 字符串内置方法详解 为何要有字符串?相对于元组.列表等,对于唯一类型的定义,字符串具有最简单的形式. 字符串往往以变量接收,变量名.可以查看所有的字符串的内置方法,如: 1> count: ...
- android组件用法说明,Android第三方控件PhotoView使用方法详解
Android第三方控件PhotoView使用方法详解 发布时间:2020-10-21 15:06:09 来源:脚本之家 阅读:74 作者:zhaihaohao1 PhotoView的简介: 这是一个 ...
- java中迭代器要导包吗_java 中迭代器的使用方法详解
java 中迭代器的使用方法详解 前言: 迭代器模式将一个集合给封装起来,主要是为用户提供了一种遍历其内部元素的方式.迭代器模式有两个优点:①提供给用户一个遍历的方式,而没有暴露其内部实现细节:②把元 ...
- python清空集合_python集合删除多种方法详解
这篇文章主要介绍了python集合删除多种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 删除指定的元素 A={'a','c','b','d ...
- python创建双链表_Python双链表原理与实现方法详解
本文实例讲述了Python双链表原理与实现方法.分享给大家供大家参考,具体如下: Python实现双链表 文章目录 Python实现双链表 单链表与双链表比较 双链表的实现 定义链表节点 初始化双链表 ...
- 线程池invokeAll方法详解
线程池invokeAll方法详解 问题起源与抽象 问题排查与猜测 猜测一:invokeAll 在异步执行后会不会同步等待线程执行完毕获取最终结果 猜测二:队列里面可能存在第一次调用 invokeAll ...
最新文章
- python教程:ConfigParser模块使用教程
- 在北上广,年薪不到40W意味着什么?
- 创建使用模块与datetime模块使用
- java被安全阻止解决及用友Uclient安装
- matlab导入vgg16,简单导入VGG16
- c语言分形程序,C语言实现分形图形
- 关于docker容器中,外网访问阿里云服务器中tomcat,报404错误的解决方法
- 找到小菇凉(BFS)
- 淘宝订单自动确认收货的N种实现,秒杀面试官
- 51jiqiren小语种语音机器人
- 小武与retinanet的斗争
- vscode撤销删除快捷键_在Windows资源管理器中使用键盘快捷键撤消意外移动或删除...
- Text函数对转换日期,调整数值,条件判断的应用技巧
- 数商云化妆品行业电商平台系统解决方案
- 为了适应云数据库mySQL产品_金山云数据库RDSMySQL的产品功能大解析
- RTL8762 开发板试用
- NC14548-B-逃脱(bfs)
- Java中的动态代理详解
- Mac电脑上如何关闭屏幕时间
- 丰田召回事件的深层次原因