在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被遗漏了。
- 浏览: 179196 次
- 性别:
- 来自: 北京
最新评论
-
ls0609:
语音实现在线听书http://blog.csdn.net/ls ...
ANDROID语音识别示例 -
AILIKES:
1927105 写道示例中219应该才是虚拟IP多谢指正,21 ...
虚拟IP原理 -
gaoke:
1927105 写道示例中219应该才是虚拟IP是的
虚拟IP原理 -
lubacui:
我居然看完了,貌似有些道理。
如何掌控自己的时间,并改变现状? -
1927105:
示例中219应该才是虚拟IP
虚拟IP原理
相关推荐
下面小编就为大家带来一篇正确遍历删除List中的元素方法(推荐)。小编觉得挺不错的,在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
主要介绍了C#遍历List并删除某个元素的方法,实例分析了正序与倒序遍历list及删除元素的使用技巧,需要的朋友可以参考下
主要介绍了C++ STL list 遍历删除出错解决方案的相关资料,这里对出错进行分析,并给出正确的解决方法,需要的朋友可以参考下
下面小编就为大家带来一篇java中循环遍历删除List和Set集合中元素的方法(推荐)。小编觉得挺不错的,在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
List集合遍历和删除操作
java数组遍历 删除remove。需要的朋友可以过来参考下,希望对大家有所帮助
初学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_...
在本篇文章中小编给大家分享了关于HashMap和List遍历方法及如何遍历删除元素知识点总结,需要的朋友们参考下。
如果从头到尾正序遍历删除的话,有些符合删除条件的元素会成为漏网之鱼; 正序删除举例: List<string> tempList = new List() { "a","b","b","c" }; for (int i = 0; i < tempList.Count; i++) { if ...
Iterator遍历中 ConcurrentModificationException异常
在遍历list的时候,删除符合条件的数据,可是总是报异常,代码如下: num_list = [1, 2, 3, 4, 5] print(num_list) for i in range(len(num_list)): if num_list[i] == 2: num_list.pop(i) else: print(num_...
主要介绍了解决JAVA遍历List集合时,删除数据出现的问题,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
java使用ListIterator对List遍历时添加修改删除
这是最近面试时被问到的1道面试题,本... List platformList = new ArrayList(); platformList.add("博客园"); platformList.add("CSDN"); platformList.add("掘金"); for (String platform : platformList) { if
再看下面,利用index来遍历删除列表l l = [1, 2, 3, 4] for i in range(len(l)): if l[i] == 4: del l[i] print l 这样没问题,可以遍历删除,但是列表l如果变为 l = [1,2,3,4,5] 如果还是按照上面的方法,设
主要介绍了Java list利用遍历进行删除操作3种方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下