List remove时出错"ConcurrentModificationException"

本文探讨了在Java中遍历List时删除元素所引发的ConcurrentModificationException异常,并提供了两种不同的实现方式来避免该问题。

1. 现象: 在遍历list的时候,出现如下错误

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at com.mylist.test.ListTest.removeFun1(ListTest.java:25)
at com.mylist.test.ListTest.main(ListTest.java:13)


2.  参考代码

package com.mylist.test;

import java.util.ArrayList;
import java.util.List;


public class ListTest {


List<String> strList = new ArrayList<String>();

public static void main(String args[]){
ListTest t = new ListTest();
t.init();
t.removeFun1("a");     // 这里出错, 出错信息就是上面开头提到的
//t.removeFun2("a");  //正确,
t.print();
}

public void init(){
strList.add("a");
strList.add("b");
strList.add("c");
}


//这种方法是java后来增加的一种语法,这里,remove的时候就会出错了
public void removeFun1(String str) {
for (String tmpStr: strList) {
if (str.equals(tmpStr)) {
strList.remove(str);
}
}
}

//这是传统的for循环的写法,能够正确执行remove.

public void removeFun2(String str) {
for (int i = 0;i< strList.size();i++) {
if (str.equals(strList.get(i))) {
strList.remove(strList.get(i));
}

}
}

public void print() {
for (String tmpStr: strList) {
System.out.println(tmpStr);


}
}


3. 分析:请参考下面这个文章


http://blog.youkuaiyun.com/smcwwh/article/details/7036663



### Java List 错误解决方案 #### Unchecked Cast 警告 当执行强制转换操作 `unchecked cast` ,编译器会发出警告提示潜在的安全隐患。对于从 `Object` 到泛型类型的转换,可以采用抑制警告的方式处理: ```java @SuppressWarnings("unchecked") List<String> stringList = (List<String>) object; ``` 不过更推荐的做法是在设计阶段就避免这种不安全的操作,通过使用通配符或其他方式来改进代码结构[^1]。 #### Fail-Fast 机制下的 Remove 方法异常 Java 集合框架中的某些实现类遵循 fail-fast 原则,在迭代过程中修改集合可能会抛出并发修改异常 (`ConcurrentModificationException`)。为了避免这种情况发生,建议利用迭代器来进行元素的移除工作: ```java Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()) { Integer element = iterator.next(); if (condition) { // 替换成实际条件判断逻辑 iterator.remove(); } } ``` 此方法能够有效防止由于直接调用 `remove()` 所引发的问题[^2]。 #### 使用 removeAll 进行批量删除 为了高效地清除列表中指定子集的内容,可借助于 `removeAll(Collection<?> c)` 函数完成这一任务。下面是一个具体的例子展示如何运用该函数去除两个整数列表之间的交集部分: ```java ArrayList<Integer> list1 = new ArrayList<>(Arrays.asList(1, 2, 3, 6)); ArrayList<Integer> list2 = new ArrayList<>(Arrays.asList(1, 2, 3, 1, 2, 3, 4, 5)); System.out.println("list1元素:" + list1); System.out.println("list2删除前:" + list2); // 移除 list2 中存在的所有属于 list1 的元素 list2.removeAll(list1); System.out.println("list2删除后:" + list2); ``` 这段程序最终输出的结果将是 `[4, 5]`,表明成功清除了共同拥有的数值项[^3]。 #### 清理 Null 元素 针对含有空值的情况,可以通过如下手段一次性剔除所有的 `null` 成员: ```java list.removeAll(Collections.<Integer>singleton(null)); ``` 这里需要注意的是,`Collections.singletonList(null)` 创建了一个不可变单例集合仅含一个 `null` 对象实例;而 `removeAll` 接受任意实现了 Collection 接口的对象作为参数并从中排除匹配项。因此上述语句能有效地清理掉目标容器里的每一个 `null` 条目[^4][^5]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值