在Java中有时候我们会需要对List里面的符合某种业务的数据进行删除,但是如果不了解里面的机制就容易掉入“陷阱”导致遗漏或者程序异常。本文以代码例子的方式进行说明该问题
1.采用Foreach循环遍历的方式
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Test1");
list.add("Test2");
list.add("Test3");
list.add("Test4");
list.add("隐藏");
for (String string : list) {
if( StringUtils.isNotBlank(string)&& (string).contains("隐藏")){
list.remove(string);
}
}
for(String s : list){
System.out.println(s);
}
}
输出结果:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at com.suning.test.TestMain.main(TestMain.java:23)
从运行结果看到程序抛ConcurrentModificationException。
JDK的API中对该异常描述为:
public class ConcurrentModificationException extends RuntimeException当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不确定的。
如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败迭代器,
因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。
注意,此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。
例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。
注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。
快速失败操作会尽最大努力抛出 ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,
正确做法 是:ConcurrentModificationException 应该仅用于检测 bug。
Java中的For each实际上使用的是iterator进行处理的。而iterator是不允许集合在iterator使用期间删除的。所以导致了iterator抛出了ConcurrentModificationException 。
2.在遍历List过程中Iterator删除元素的做法:
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Test1");
list.add("Test2");
list.add("Test3");
list.add("Test4");
list.add("隐藏");
for(Iterator<String> it = list.iterator();it.hasNext();){
String s=it.next();
if( StringUtils.isNotBlank(s)&& (s).contains("隐藏")){
it.remove();
}
}
for(String s : list){
System.out.println(s);
}
}
输出结果:
Test1
Test2
Test3
Test4
对于iterator的remove()方法,也有需要我们注意的地方:
1、每调用一次iterator.next()方法,只能调用一次remove()方法。
2、调用remove()方法前,必须调用过一次next()方法。
以下是JDK-API中对于remove()方法的描述:
void remove()
从迭代器指向的集合中移除迭代器返回的最后一个元素(可选操作)。每次调用 next 只能调用一次此方法。
如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的集合,则迭代器的行为是不明确的。
抛出:UnsupportedOperationException - 如果迭代器不支持 remove 操作。
IllegalStateException - 如果尚未调用 next 方法,或者在上一次调用 next 方法之后已经调用了remove 方法。
3.用for循环遍历删除数组元素
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Test1");
list.add("Test2");
list.add("Test3");
list.add("Test4");
list.add("隐藏");
list.add("隐藏2");
list.add("隐藏3");
list.add("隐藏4");
for (int i = 0; i < list.size(); i++) {
if (StringUtils.isNotBlank(list.get(i)) && list.get(i).contains("隐藏")) {
list.remove(i);
}
}
for(String s : list){
System.out.println(s);
}
}
输出结果:
Test1
Test2
Test3
Test4
隐藏2
隐藏4
我们是想删除包含“隐藏”的元素,但结果显示只删除了一个,另一个“隐藏”被遗漏了,
原因是:删除了第一个“隐藏”后,集合里的元素个数减1,后面的元素往前移了1位,导致了第二个2被遗漏了。
- 浏览: 186382 次
- 性别:
- 来自: 北京
最新评论
-
ls0609:
语音实现在线听书http://blog.csdn.net/ls ...
ANDROID语音识别示例 -
AILIKES:
1927105 写道示例中219应该才是虚拟IP多谢指正,21 ...
虚拟IP原理 -
gaoke:
1927105 写道示例中219应该才是虚拟IP是的
虚拟IP原理 -
lubacui:
我居然看完了,貌似有些道理。
如何掌控自己的时间,并改变现状? -
1927105:
示例中219应该才是虚拟IP
虚拟IP原理
相关推荐
以下是几种常见的遍历删除List元素的方法及其注意事项: 1. **通过增强的for循环删除元素** - **问题**:在增强的for循环(foreach)中直接删除元素会导致`ConcurrentModificationException`,因为这种方式不允许...
当我们需要遍历List并根据条件删除特定元素时,需要注意正确的方法,以避免在遍历过程中出现错误。以下将详细介绍如何在C#中遍历List并删除元素,包括正序和倒序遍历的技巧。 首先,我们来看一下错误的遍历方式。...
本篇文章主要探讨的是在使用STL list时遇到的遍历删除元素过程中常见的错误及其解决方案。 错误用法通常出现在尝试同时遍历和删除list中的元素时。以下是三种常见的错误做法: 1. 错误用法一: 在这个例子中,迭代...
**错误的遍历删除方式** 错误的示例代码如下: ```java Set<CheckWork> set = this.getUserDao().getAll().get(0).getActionCheckWorks(); for (CheckWork checkWork : set) { if (checkWork.getState() == 1) { ...
HashMap和List遍历方法及如何遍历删除元素总结 HashMap和List都是Java中最常用的数据结构,它们都可以用来存储和操作数据。然而,在遍历和删除元素时,需要小心地处理,以免出现问题。下面总结了HashMap和List的...
本测试着重关注四种常见的集合类型:ArrayList、Dictionary, TValue>、List以及DataSet,它们各自在遍历性能上的差异。遍历性能是衡量代码执行效率的重要指标,尤其在大数据量处理时,高效的遍历方法能显著提升程序...
List集合遍历和删除操作
如果在遍历过程中删除元素,通常需要使用迭代器(Iterator)来安全地进行,因为迭代器会跟踪当前元素并处理删除后的调整。 最后,输出了ArrayList的大小以及所有学生的姓名、学号和颜色。遍历结束后,输出显示...
初学Python,遇到过这样的问题,在遍历list的时候,删除符合条件的数据,可是总是报异常,代码如下: num_list = [1, 2, 3, 4, 5] print(num_list) for i in range(len(num_list)): if num_list[i] == 2: num_...
总之,在Android中遍历和删除指定类型的文件是一项常见的任务,涉及到文件操作、遍历算法以及条件判断。开发者需要了解`java.io.File`类的使用,并根据需要处理不同类型的文件。在实际应用中,还应注意权限管理以及...
本资料主要探讨如何遍历Java中的List集合,包括基本的迭代器方式、增强for循环(foreach)以及流(Stream)API的使用。下面我们将深入讲解这些遍历方法。 1. 迭代器(Iterator)遍历: Java中的List接口定义了...
如果从头到尾正序遍历删除的话,有些符合删除条件的元素会成为漏网之鱼; 正序删除举例: List<string> tempList = new List() { "a","b","b","c" }; for (int i = 0; i < tempList.Count; i++) { if ...
解决JAVA遍历List集合删除数据时出现的问题 JAVA 中遍历List集合时删除数据出现的问题是很多开发者经常遇到的问题,本文对该问题进行了详细的讲解,总结了多种解决方法,并对问题的原因进行了深入分析。 问题描述...
在Java编程中,`Iterator`是用于遍历集合(如`List`, `Set`等)的重要工具。然而,当我们尝试在使用`Iterator`遍历集合的过程中直接修改集合时,可能会遇到`ConcurrentModificationException`异常。这个异常通常发生...
如果在遍历过程中需要删除元素,只能使用`it.remove()`,而不能直接使用`list.remove()`,否则可能会引发并发访问错误。 2. 使用增强型`for`循环(也称为foreach循环): ```java List list = new ArrayList(); // ...
如果你需要对每个文件或子目录进行进一步的操作,如读取、删除或重命名,`listFiles()`是更好的选择。 3. **递归遍历**:如果目录中还有子目录,我们需要递归地遍历它们。通常,我们会创建一个递归函数,当遇到子...
在 Java 编程中,遍历 List 集合是一项常见的任务,特别是在处理...这些方法使 List 成为处理有序数据的强大工具,可以方便地进行插入、删除、查找和修改等操作。在实际编程中,根据需求选择合适的遍历方法至关重要。
在Java编程中,遍历并删除List集合是一个常见的操作,但在实际编程中,如果不使用正确的方法,可能会导致`java.util.ConcurrentModificationException`异常。本文主要针对这个面试题,详细讲解如何在遍历List的同时...