List 集合遍历过程中删除元素。这个坑踩一遍就不要再踩了!

这篇具有很好参考价值的文章主要介绍了List 集合遍历过程中删除元素。这个坑踩一遍就不要再踩了!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作为一名后端开发,不管采用什么语言 使用 List 集合的频率都非常高。

对 List 集合的遍历和遍历中操作数据也是家常便饭。

我从我使用的过程中对于此问题的思考与实践形成记录,与大家交流。有不对的地方,恳请大家指正。

1. 遍历

List 集合的遍历有很多种方式,每一种遍历方式只有性能上的差异,不会有异常和暗坑。这里不再赘述。


2. 遍历过程中删除元素

因为 List 集合有多种遍历方式,也就意味着存在多种遍历中删除的方式:

在做各种方式比对前,我们先加入一些初始数据。

 List<String> list = new ArrayList<>();
 list.add("snow");
 list.add("nier");
 list.add("sar");
 list.add("juaya");
 list.add("rock");
 list.add("snow");
 list.add("nier");

2.1 for 简单循环正向遍历方式

for (int i = 0; i < list.size(); i++) {
	String name = list.get(i);
	if(name.equals("snow")){
		list.remove(i);
	}
	if(name.equals("nier")){
		list.remove(i);
	}
}

System.out.println(list);

上述代码打印结果:

 [nier, sar, juaya, rock, nier]

很明显 这不是正确的结果。
这是 因为:在遍历过程中,删除或者增加元素后,集合长度会因为实时改动而改动,也就是说集合在遍历过程中忘了初心了。

举个栗子:现在对长度为 5 的集合进行遍历,在遍历到 第三个元素的时候删除了ta,那么此时集合长度成了4,那么此时集合就不会遍历到之前下标为 5 的元素了。

知道了原因后,我们可以对症下药,达到我们的预期。修改代码如下:

for (int i = 0; i < list.size(); i++) {
	String name = list.get(i);
	if(name.equals("snow")){
		list.remove(i);
		//	加补偿机制
		i--;
	}
	if(name.equals("nier")){
		list.remove(i);
		//	加补偿机制
		i--;
	}
}

System.out.println(list);

上述代码执行结果:

[sar, juaya, rock]

如此 加入了补偿机制后虽然达到了预期结果。但是很明显代码不够优雅。So 这种方式不推荐。


2.2 for 简单循环反向遍历方式

反向遍历和正向遍历类似,只不过是反方向的钟而已。

for (int i = list.size() - 1; i >= 0; i--) {
	String name = list.get(i);
	if(name.equals("snow")){
		list.remove(i);
	}
	if(name.equals("nier")){
		list.remove(i);
	}
}

System.out.println(list);

上述代码执行结果:

[sar, juaya, rock]

咦~可以哎。结果正确。那这种方式是不是就绝对可以了呢。 NO!

逆序遍历虽然在这个场景下达到了预期的正确结果,但是因为 这种方式和正序在原理上是相同的。所以在遍历过程中操作元素也会有其劣根性。比如在逆序遍历过程中加入元素,依然会对整个遍历产生影响。 所以这也不是推荐的方式。


2.3 foreach 方式遍历删除

单从遍历来看 这种方式比上述两种方式优雅了不少。但是遍历过程中操作元素能达到预期结果吗?

for (String s : list) {
	if(s.equals("rock")){
		list.remove("rock");
	}
}

执行结果…
list遍历删除元素,Java,list,java,数据结构

What???

list遍历删除元素,Java,list,java,数据结构

原因: 这种循环方式,其生成的字节码其实使用的 Iterator ,使用的核心方法是 `hasnext()` 和 `next()`。 然后再来看下ArrayList类的 Iterator 是如何实现的呢? Iterator 部分源码:

list遍历删除元素,Java,list,java,数据结构

可以看出:调用next()方法获取下一个元素时,第一行代码就是调用了checkForComodification();

而该方法的核心逻辑就是比较 modCountexpectedModCount 这2个变量的值。
在上面的例子中,刚开始 modCountexpectedModCount 的值都为 n,所以第1次获取元素 “rock” 是没问题的,但是当执行完下面这行代码时:

list.remove("rock");

modCount 的值就被修改了。
list遍历删除元素,Java,list,java,数据结构
So: 使用 foreach 遍历过程中删除元素是不可行的。


2.4 Iterator的remove()方法

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
    String next = iterator.next();
    if("snow".equals(next)){
        iterator.remove();
    }
}

执行结果:

[nier, sar, juaya, rock, nier]

很 nice !

那这种方式怎么就可以删除了呢???
list遍历删除元素,Java,list,java,数据结构

因为:

这种方式每次删除一个元素,都会将modCount 的值重新赋值给 expectedModCount,这样2个变量就相等了,不会触发 java.util.ConcurrentModificationException 异常。

list遍历删除元素,Java,list,java,数据结构

虽然这种方式符合了业务要求,但是还是不推荐这种方式,因为他的写法依然不够优雅。


2.5 removeIf() (推荐)

从JDK1.8开始,可以使用 removeIf() 方法来代替 Iterator的remove()方法实现一边遍历一边删除。

list.removeIf(s -> s.equals("snow"));

System.out.println(list);

打印结果:

[nier, sar, juaya, rock, nier]

其源码如下:
list遍历删除元素,Java,list,java,数据结构


2.6 Strem 方式

list = list.stream().filter( name -> !("snow".equals(name) ) ).collect(Collectors.toList());

System.out.println(list);

filter 过滤会保留满足条件的。

结果如下:文章来源地址https://www.toymoban.com/news/detail-521364.html

[nier, sar, juaya, rock, nier]

到了这里,关于List 集合遍历过程中删除元素。这个坑踩一遍就不要再踩了!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 遍历List集合

    最基础的遍历方式:for循环,指定下标位置,使用 List 集合的 get(i) 方法来获取元素。

    2024年02月07日
    浏览(30)
  • Java遍历集合元素并修改

    结论:fori循环可以修改、删除、添加,但是要注意的是下标还是元素;增强for循环内,可以修改,不可以删除、添加。想要删除、添加,使用集合迭代器的删除、添加方法。 对List和Set的遍历,有四种方式,下面以ArrayList为例进行说明。 1.1 fori循环 使用普通for循环的遍历方式

    2024年02月06日
    浏览(36)
  • List集合的五种遍历方式

    目录 一、List五种遍历方式  1、普通for遍历 2、 增强for遍历  3、Lambda表达式  4、迭代器遍历  5、列表迭代器 方法 说明 迭代器遍历 在遍历的过程中需要删除元素,请使用迭代器。 列表迭代器 在遍历的过程中需要添加元素,请使用列表迭代器。 增强for遍历 仅仅想遍历,那

    2024年02月10日
    浏览(44)
  • 【Java】List集合遍历的五种方法

    🎊专栏【Java】 🌺每日一句:人生最重要的就是要清醒的认知 ⭐欢迎并且感谢大家指出我的问题 目录 1.通过for循环配合List接口中的size()和get(index i)的方法 2.使用Iterator迭代器及其方法遍历集合 🍔迭代器 🍔具体操作 3.增强for循环遍历 🍔是for循环的一种 🍔格式 🍔好处 🍔弊

    2024年02月03日
    浏览(53)
  • JS循环遍历并删除指定元素

    昨天一个朋友让我帮她修改的一段代码: 需求要每条数据轮播1分钟,然后删除,运行的时候会发现foreach循环中,删除一个之后,其他的就无法删除了。 【分析原因】 数据格式例如:[\\\'a\\\',\\\'b\\\',\\\'b\\\',\\\'c\\\'],需求是删除item为‘b’的元素 第一次循环:SysNotices数据:[\\\'a\\\',\\\'b\\\',\\\'b\\\',\\\'c\\\'],in

    2024年02月09日
    浏览(47)
  • java List 删除 元素

    1.for循环倒序删除 2.迭代器删除 3.lamda stream流过滤

    2024年02月15日
    浏览(44)
  • python 一次性删除列表(list)的空白元素(空内容) 或者 一次性删除列表(list)中的指定元素

    看看下述代码: 输出: 当你遇见这种情况,有哪些方法来去除里面的空内容呢(即 \\\'\\\' )? 1.1 删除空内容(方法一) : 输出: 1.2 删除空内容(方法二) : 需要 配合 lambda 表达式 一起使用! 输出: 2.3 删除指定内容 : 输出: 注 :此方法既可以删除空元素,也可以删除指

    2024年02月03日
    浏览(86)
  • 【Java】遍历 Map 时删除 Map 中元素

    https://blog.csdn.net/LSKCGH/article/details/97521668 https://www.jianshu.com/p/a3b3aae6697c 不能直接在 Map 的 for 循环中使用 remove 方法,会抛出 ConcurrentModificationException 异常,应使用迭代器中的 remove 方法删除元素。 以下代码运行时会抛出 ConcurrentModificationException: 解决方案如下: 示例1: 示例

    2024年02月16日
    浏览(35)
  • Java 中 List 删除元素

    删除某个元素后,list的大小发生了变化,会导致遍历准确。 这种方式可以用在删除特定的一个元素时使用,但不适合循环删除多个元素时使用 删除元素后继续循环会报错误信息 ConcurrentModificationException ,但是删除完毕马上使用break跳出,则不会触发报错。 iterator遍历过程中

    2024年02月09日
    浏览(42)
  • Java List集合去重、过滤、分组、获取数据、求最值、合并、排序、跳数据和遍历

    请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i、 使用stream().map()提取List对象的某一列值及去重 使用 findAny() 和 findFirst() 获取第一条数据 我是南国以南i记录点滴每天成长一点点,学习是永无止境的!转载请附原文链接!!! 参考链接、参考链接

    2024年04月11日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包