ArrayList中的遍历删除

例如我们有下列数据,要求遍历列表并删除所有偶数。

List myList = new ArrayList<>(Arrays.toList(new Integer[]{2, 3, 5, 8, 10, 9}));

代码1:直接遍历列表并删除(错误)

初学者可能会直观地认为,我直接一个for循环遍历删除不就好了吗?但实际上这种做法是错误的。

static void remove1(List 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 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 list) {
    Iterator iterator = list.iterator();
    while (iterator.hasNext()) {
        Integer next = iterator.next();
        if (next % 2 == 0) {
            iterator.remove();
        }
    }
}

代码4:使用 removeIf() 方法

static void remove4(List list) {
    list.removeIf(new Predicate() {
        @Override
        public boolean test(Integer i) {
            return i % 2 == 0;
        }
    });
}

或者采用 lambda 表达式,更简洁:

list.removeIf(i -> i % 2 == 0);

以上就是对列表遍历删除的方法总结。如果条件比较简单,可以直接采用 removeIf() 方法,如果条件比较复杂,那么采用迭代器是一种比较好的方法。

Original: https://www.cnblogs.com/ryuasuka/p/15845660.html
Author: 飞鸟_Asuka
Title: ArrayList中的遍历删除

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/609188/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 实验二 电子传输系统安全-进展2

    一、利用java程序实现文件加密 我们的文件在计算机中都是以二进制的形式存储,而Java中IO流(字节流和字符流)可以实现对底层文件的读取,故利用Java的IO流进行文件拷贝时,可…

    Linux 2023年6月8日
    0102
  • 我懂得了什么

    站在24岁的这个档口,没有学业又没有工作的时刻,前不着村后不着店。我觉得应该要写一些总结,虽然年仅24的我相比老人家总结不出更深刻的道理,但是现在是互联网的时代,获取知识的途径已经…

    Linux 2023年6月6日
    096
  • apparmor 源码分析

    这里不对apparmor做介绍,记录一下源码分析过程。 static int __init apparmor_init(void) -> security_add_hooks…

    Linux 2023年6月13日
    072
  • 每周一个linux命令(ls)

    title: 每周一个linux命令(ls) date: 2021-10-10 09:18:00 tags: [ls,每周一个linux命令] categories: linux …

    Linux 2023年5月27日
    0117
  • springboot2 整合 redis 并通过 aop 实现自定义注解

    1,相关依赖 pom.xml 片段 org.springframework.boot spring-boot-starter-aop org.springframework.boo…

    Linux 2023年5月28日
    0101
  • Docker部署Dotnet

    方法一:打包+镜像 部署 将要部署的项目及其依赖的项目上传至指定文件夹下 要部署的项目添加Docker支持,生成Dockerfile文件 将生成的Dockerfile文件上传至要部…

    Linux 2023年6月13日
    0111
  • mongodb压力测试工具ycsb

    mongodb安装 这里以安装单机版为例,rpm包方式安装 启动 ​ systemctl start mongod YCSB压测工具安装 这里不采用网上大多说的maven方式源码安…

    Linux 2023年6月14日
    087
  • 高速USB转4串口产品设计-TTL串口

    基于480Mbps 高速USB转8路串口芯片CH344Q,可以为各类主机扩展出4个独立的串口。CH344芯片支持使用操作系统内置的CDC串口驱动,也支持使用厂商提供的VCP串口驱动…

    Linux 2023年6月7日
    0104
  • [Linux] 如何在 Linux 电脑上制作专业的视频教程

    前言 1、软件工具准备 a. 录音软件 b. 录屏软件 c. 摄像头软件 d. 安卓屏幕操作软件 e. 视频剪辑软件 2、视频教程制作 3、效果 参考链接 前言 博主使用 Arch…

    Linux 2023年6月8日
    0112
  • docker部署安装Nginx

    docker部署安装Nginx 前言 Nginx是一个高性能的HTTP和反向代理web服务器,同事也提供了IMAP/POP3/SMTP服务。特点: 轻量级的Web服务器/反向代理服…

    Linux 2023年6月6日
    090
  • 深入理解Java类加载机制,再也不用死记硬背了

    谈谈”会”的三个层次 在《说透分布式事务》中,我举例里说明了会与会的差别。对一门语言的学习,这里谈谈我理解的”会”的三个层次: 第一…

    Linux 2023年6月14日
    098
  • ThinkPHP5.x.x各版本实战环境getshell

    <span>http<span>:<span>//www.xxxxx.com/?s=admin/\think\app/invokefunctio…

    Linux 2023年5月28日
    073
  • linux root用户编辑文件提示没有权限

    linux root用户编辑文件提示没有权限 感觉很奇怪,因为是root用户。于是查看了一下文件的权限,结果如下: [root@localhost elasticsearch-5….

    Linux 2023年6月8日
    0100
  • 数据结构 二叉树

    cpp;gutter:true;</p> <h1>include</h1> <p>using namespace std;</…

    Linux 2023年6月13日
    074
  • CKS考试心得分享

    CKS证书 考试相关 考试报名准备 CKS考试和CKA考试一样,已经开放中国大陆的考试。但区别是CKS目前没有中文题目,考试都是英文题目,唯一区别是CKS中文考试是中文老师监考,仅…

    Linux 2023年6月13日
    088
  • Android recovery支持adb shell

    Android recovery支持adb shell 近期开发过程注意到recovery不支持adb shell。为了便于调试方便,决定添加此功能。 刚開始我们採用的是user版…

    Linux 2023年5月28日
    097
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球