JAVA中循环遍历list有三种方式for循环、增强for循环(也就是常说的foreach循环)、iterator遍历。

1、for循环遍历list

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

  这种方式的问题在于,删除某个元素后,list的大小发生了变化,而你的索引也在变化,所以会导致你在遍历的时候漏掉某些元素。比如当你删除第1个元素后,继续根据索引访问第2个元素时,因为删除的关系后面的元素都往前移动了一位,所以实际访问的是第3个元素。因此,这种方式可以用在删除特定的一个元素时使用,但不适合循环删除多个元素时使用。

2、增强for循环

for(String x:list){
if(x.equals("del"))
list.remove(x);
}

  这种方式的问题在于,删除元素后继续循环会报错误信息ConcurrentModificationException,因为元素在使用的时候发生了并发的修改,导致异常抛出。但是删除完毕马上使用break跳出,则不会触发报错。

3、iterator遍历(推荐)

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

  这种方式可以正常的循环及删除。但要注意的是,使用iterator的remove方法,如果用list的remove方法同样会报上面提到的ConcurrentModificationException错误。

  总结:

  (1)循环删除list中特定一个元素的,可以使用三种方式中的任意一种,但在使用中要注意上面分析的各个问题。

  (2)循环删除list中多个元素的,应该使用迭代器iterator方式。

---20200427↓---

4.使用Java 8中提供的filter过滤

Java 8中可以把集合转换成流,对于流有一种filter操作, 可以对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream。

List<String> userNames = new ArrayList<String>() {{
add("Hollis");
add("hollis");
add("HollisChuang");
add("H");
}}; userNames = userNames.stream().filter(userName -> !userName.equals("Hollis")).collect(Collectors.toList());
System.out.println(userNames);//[hollis, HollisChuang, H]

5.使用增强for循环其实也可以

如果,我们非常确定在一个集合中,某个即将删除的元素只包含一个的话, 比如对Set进行操作,那么其实也是可以使用增强for循环的,只要在删除之后,立刻结束循环体,不要再继续进行遍历就可以了,也就是说不让代码执行到下一次的next方法。

List<String> userNames = new ArrayList<String>() {{
add("Hollis");
add("hollis");
add("HollisChuang");
add("H");
}}; for (String userName : userNames) {
if (userName.equals("Hollis")) {
userNames.remove(userName);
break;
}
}
System.out.println(userNames);//[hollis, HollisChuang, H]

6.使用fail-safe的集合类

在Java中,除了一些普通的集合类以外,还有一些采用了fail-safe机制的集合类。这样的集合容器在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。

由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发ConcurrentModificationException。

ConcurrentLinkedDeque<String> userNames = new ConcurrentLinkedDeque<String>() {{
add("Hollis");
add("hollis");
add("HollisChuang");
add("H");
}}; for (String userName : userNames) {
if (userName.equals("Hollis")) {
userNames.remove();
}
}
System.out.println(userNames);//[hollis, HollisChuang, H]

基于拷贝内容的优点是避免了ConcurrentModificationException,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。

java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

JAVA中循环删除list中元素的更多相关文章

  1. Java中循环删除list中元素的方法总结

    印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后在今天使用的时候发现报错了,然后去科普了一下,发现这是一个误区.下面我们来一起看一下. Java中循环遍 ...

  2. JAVA中循环删除list中元素的方法总结【转】

    印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个误区.下面就来讲一讲..伸手党可直接跳至文末 ...

  3. JAVA中循环删除list中元素的方法总结(同上篇)

    印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个误区.下面就来讲一讲..伸手党可直接跳至文末 ...

  4. java中循环删除list中元素的方法

    重点哈 印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个误区.下面就来讲一讲..伸手党可直接 ...

  5. python中循环删除列表中元素时的坑!

    循环删除列表中元素时千万别用正序遍历,一定要用反序遍历! 废话不多说,先上案例代码: def test(data): for i in data: data.remove(i) return data ...

  6. for循环删除list中多个元素出现的误区

    错误的做法是: for(int i= 0;i<list.size();i++) 因为在你删除元素的同时list.size()也在变小,这样就会照成越界. 正确做法:因为要删除list里面的多个的 ...

  7. JS实现循环删除数组中元素的方法介绍

    这篇文章主要给大家介绍了关于Javascript循环删除数组中元素的几种方法,文中给出了详细的示例代码供大家参考学习,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧. 本文主要跟大家分享了 ...

  8. python中如何删除列表中的所有元素

    今天写代码的时候遇到一个小问题,Python中要删除列表中的所有元素.Python本身就提供了pop.remove.del这些删除的函数.我想着用循环实现,结果很麻烦.几番周折上了stackoverf ...

  9. JS中如何删除某个父元素下的所有子元素?

    JS中如何删除某个父元素下的所有子元素?这里我介绍几种方法: 1.通过元素的 innerHTML 属性来删除 这种方式我觉得是最有方便的,直接找到你想要的父元素,直接令其 element.innerH ...

随机推荐

  1. jquery获取select多选框选中的值

    select下拉框选中的值,用jquery大家应该都会获取, $("#selectBox option:selected").val(); 如果select是多选的,也这么获取的话 ...

  2. K3 WISE安全认证方式

    k/3中间层注册三种安全认证方式: 交互式用户方式,网络服务方式,信任方式,是指组件服务中生成的COM+应用程序中的组件包的运行账户(注册中间层后产生很多ebo开头的和kdsvrmgr组件包). 三种 ...

  3. java之序列化

    详细内容 连接https://blog.csdn.net/qq_27093465/article/details/78544505 Java 之 Serializable 序列化和反序列化的概念,作用 ...

  4. C#中as运算符

    as运算符用于执行引用类型的显式类型转换.如果要转换的类型与指定的类型兼容,转换就会成功进行:如果类型不兼容,as运算符就会返回null值.如下面的代码所示,如果object引用实际上不引用strin ...

  5. python设计模式第二十四天【命令模式】

    1.使用场景 (1)调用过程比较繁琐,需要封装 (2)调用参数需要进行处理封装 (3)需要添加额外的功能,例如,日志,缓存,操作记录等 2.代码实现 #!/usr/bin/env python #! ...

  6. QTP 自动货测试桌面程序-笔记(添加控件仓库并关联到action)

    录制或编写脚本前先添加行为对应的控件仓库: 心得:多个测试action使用的同一个窗体的仓库单独放于一个仓库中,可以在多个action中添加关联使用 将同一个窗体的控件只放于一个仓库中,减少使用时的名 ...

  7. python 计算机基础

    1.什么是编程语言. 语言是一个事物与另一个事物沟通的介质. 编程语言是程序员与计算机沟通的介质. 2.什么是编程. 编程是人按照某种语法规范设计出计算机能够识别的语言 表达的结果是程序,程序就是一系 ...

  8. SQL Server中获取指定时间段内的所有月份

    例如查询 2012-1-5 到 2012-11-3 之间所有的月份 declare @begin datetime,@end datetime set @begin='2012-1-5' set @e ...

  9. How to install rime on Debian

    apt-get install ibus ibus-rime librime-data-wubi reboot cp ~/.config/ibus/rime/default.yaml ~/.confi ...

  10. 性能测试工具 Locust

    https://docs.locust.io/en/latest/quickstart.html