ArrayList中的遍历删除
ArrayList 中的遍历删除
在代码编写过程中经常会遇到这样的要求:遍历一个线性表,要求只遍历一遍(时间复杂度\(O(n)\)),删除符合指定条件的元素,且要求空间复杂度 \(O(1)\)。
例如我们有下列数据,要求遍历列表并删除所有偶数。
List<Integer> myList = new ArrayList<>(Arrays.toList(new Integer[]{2, 3, 5, 8, 10, 9}));
代码1:直接遍历列表并删除(错误)
初学者可能会直观地认为,我直接一个for循环遍历删除不就好了吗?但实际上这种做法是错误的。
static void remove1(List<Integer> list) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) % 2 == 0) {
list.remove(i);
}
}
}
使用上面的测试数据,结果为:[3, 5, 7, 10, 9],其中一个偶数 10 并没有被删除。
事实上,当删除列表中元素时,列表的 size() 会改变!当第一个 2 被删除时,此时 list.size() 已经从 6 变成了 5,而 i 只会一直向前跑,因此当 8 被删除时,list.size() 为 4,此时 i 已经变为 5,不再满足 i < list.size() 的循环条件,就会退出循环,后面的元素也不会再被处理。
代码2:控制循环变量的遍历(低效)
第二种做法是,不采用 for 循环,而是采用 while 循环 + 控制循环变量 i 的做法。
static void remove2(List<Integer> list) {
int i = 0;
int j;
while (i < list.size()) {
if (list.get(i) % 2 == 0) {
j = i--;
// 此处存在 i < 0 的可能,所以要及时恢复 i 的位置
if (i < 0) {
i = 0;
}
list.remove(j); // 注意此处删除的是 j(也就是原来的 i)指向的元素
} else {
i++;
}
}
}
这里要对循环变量 i 进行控制,当删除一个元素时,i 并不能向前进一个位置而应该向后回退一个位置,从这个回退的位置开始重新向前走,才不至于遗漏本应被遍历到的元素。
代码3:使用迭代器(推荐)
一种更好的写法是使用迭代器,因为迭代器会自动判断列表中的每一个元素是否被遍历过。事实上,迭代器的实现和代码 2 很接近,但是可读性更好。
static void remove3(List<Integer> list) {
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer next = iterator.next();
if (next % 2 == 0) {
iterator.remove();
}
}
}
代码4:使用 removeIf() 方法
Java 中对 ArrayList 类还支持一种 removeIf() 方法,参数传入一个 Predicate 接口的实现对象或一个 lambda 表达式即可。
static void remove4(List<Integer> list) {
list.removeIf(new Predicate<Integer>() {
@Override
public boolean test(Integer i) {
return i % 2 == 0;
}
});
}
或者采用 lambda 表达式,更简洁:
list.removeIf(i -> i % 2 == 0);
以上就是对列表遍历删除的方法总结。如果条件比较简单,可以直接采用 removeIf() 方法,如果条件比较复杂,那么采用迭代器是一种比较好的方法。
ArrayList中的遍历删除的更多相关文章
- java中List遍历删除元素-----不能直接 list.remove()
https://blog.csdn.net/github_2011/article/details/54927531 这是List接口中的方法,List集合调用此方法可以得到一个迭代器对象(Itera ...
- 正确遍历删除List中的元素方法(推荐)
遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过增强的for循环删除符合条件的多个元素 2.通过增强的for循环删除符合 ...
- 如何正确遍历删除List中的元素
遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过增强的for循环删除符合条件的多个元素 2.通过增强的for循环删除符合 ...
- 如何正确遍历删除List中的元素(普通for循环、增强for循环、迭代器iterator、removeIf+方法引用)
遍历删除List中符合条件的元素主要有以下几种方法: 普通for循环 增强for循环 foreach 迭代器iterator removeIf 和 方法引用 其中使用普通for循环容易造成遗漏元素的问 ...
- Java 删除ArrayList中重复元素,保持顺序
// 删除ArrayList中重复元素,保持顺序 public static List<Map<String, Object>> removeDuplicat ...
- 如何使用 Java 删除 ArrayList 中的重复元素
如何使用 Java 删除 ArrayList 中的重复元素 (How to Remove Duplicates from ArrayList in Java) Given an ArrayList w ...
- Java删除ArrayList中的重复元素
Java删除ArrayList中的重复元素的2种方法 ArrayList是Java中最常用的集合类型之一.它允许灵活添加多个null元素,重复的元素,并保持元素的插入顺序.在编码时我们经常会遇到那种必 ...
- 数据结构学习-BST二叉查找树 : 插入、删除、中序遍历、前序遍历、后序遍历、广度遍历、绘图
二叉查找树(Binary Search Tree) 是一种树形的存储数据的结构 如图所示,它具有的特点是: 1.具有一个根节点 2.每个节点可能有0.1.2个分支 3.对于某个节点,他的左分支小于自身 ...
- 如何正确遍历删除List中的元素,你会吗?
遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过增强的for循环删除符合条件的多个元素 2.通过增强的for循环删除符合 ...
- Java之——删除ArrayList中的反复元素的2种方法
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47414935 ArrayList是Java中最经常使用的集合类型之中的一个.它同意 ...
随机推荐
- P1854-DP【绿】
首先通过这道题我收获了一个知识,那就是deque可以直接赋值,作用和vector类似就是复制一个一摸一样的deque,很好用,越来越发现deque眉清目秀了起来.以后deque可能是我最常用的STL结 ...
- C#设计模式15——观察者模式的写法
是什么: 观察者模式是一种设计模式,它定义了对象之间的一种一对多的依赖关系,使得当一个对象状态发生改变时,它的所有依赖者都能够得到相应的通知并作出相应的反应.观察者模式也被称为发布-订阅模式. 为什么 ...
- 机器学习-无监督机器学习-主成分分析PCA-23
目录 1. 降维的方式 2. PCA的一般步骤 3. 思想2 最小化投影距离 4. Kernelized PCA 1. 降维的方式 对于维度灾难.数据冗余,这些在数据处理中常见的场景,我们不得不进一步 ...
- 玩转 Helm
0. 前言 在 kubernetes 的系列文章中,我们介绍了 kubernetes 的种种概念,特性.不过对于如何部署并没有介绍,想象下如果 kubernetes 中 pod 的数量达到成百,上千, ...
- 每天学五分钟 Liunx 0010 | 软件篇: RPM 和 YUM
1. RPM RPM(RedHat Package Manager),顾名思义是 RedHat 的软件包管理器.它遵循 GPL 规则且功能强大好用,从而逐渐运用到其它 Liunx 发行版中,包括 Fe ...
- Postman 接口测试配置 Pre-request Script
本文为博主原创,转载请注明出处: Pre-request Script 为Postman预置脚本,用于在postman 发送请求之前执行,封装计算或获取某些请求参数. 1. postman 脚本提供 ...
- arm-none-eabi-objcopy 使用说明
译文 NAME objcopy - copy and translate object files 概要 objcopy [-F bfdname|--target=bfdname] [-I bfdna ...
- [转帖]INSERT IGNORE INTO 与 INSERT INTO
INSERT IGNORE INTO 会忽略数据库中已经存在 的数据,如果数据库没有数据,就插入新的数据,如果有数据的话就跳过当前插入的这条数据.这样就可以保留数据库中已经存在数据,达到在间隙中插入数 ...
- [转帖]Linux | crontab定时任务及开机自启项
本文总结如何使用 crontab 创建定时任务及开启自启项 1. 本文基于 CentOS 7.9 系统所写. Updated: 2022 / 9 / 5 Linux | crontab定时任务及开机自 ...
- [转帖]Linux中./configure、make、make install命令详解
简单来说,make 是编译,make install 是安装. 总结:linux编译安装中configure.make和make install各自的作用 • ./configure是用来检测你 ...