java 中的 concurrentmodificationexception 是在使用迭代器遍历集合时,检测到集合的结构被修改而抛出的异常。要复现这个问题,只需在增强 for 循环或手动调用 iterator.next() 的过程中,直接调用集合对象的 remove() 或 add() 方法即可。

为什么直接修改会触发快速失败机制
直接调用集合的修改方法会触发快速失败机制。这是因为 Java 集合(如 ArrayList)内部维护了一个 modCount 字段,每次结构改变都会递增它。迭代器在创建时会记录当前的 modCount,并在每次操作时进行比对。如果两者不一致,说明发生了非预期的并发修改,迭代器就会抛出异常以保护数据一致性。

import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<string> list = new ArrayList();
list.add("A");
list.add("B");
// 错误做法:在遍历中直接修改集合
for (String item : list) {
if (item.equals("A")) {
list.remove(item); // 触发 ConcurrentModificationException
}
}
}
}</string>
运行上述代码将立即抛出 ConcurrentModificationException。这证明了在遍历期间直接修改集合是非法的。要避免此问题,应使用迭代器提供的 remove() 方法,或者在遍历结束后再执行批量修改。
如何安全地移除元素
安全移除元素的方法是直接使用迭代器的 remove() 方法。该方法不仅会从集合中删除当前元素,还会同步更新迭代器的状态和集合的 modCount,从而保持两者的一致性,避免触发快速失败检查。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SafeRemove {
public static void main(String[] args) {
List<string> list = new ArrayList();
list.add("A");
list.add("B");
Iterator<string> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
if (item.equals("A")) {
it.remove(); // 安全移除
}
}
System.out.println(list); // 输出 [B]
}
}</string></string>
使用迭代器移除后,集合内容变为 [B],且程序正常运行。这是处理单线程下遍历时移除元素的推荐做法。对于多线程场景,则需考虑使用 CopyOnWriteArrayList 或显式加锁。
使用 removeIf 方法的处理结果
在 Java 8 及以上版本中,可以使用 removeIf 方法来过滤集合元素。该方法会在内部安全地处理结构修改,不会抛出 ConcurrentModificationException,因为它不是通过迭代器遍历来执行的,而是直接在集合内部进行遍历和删除。
import java.util.ArrayList;
import java.util.List;
public class RemoveIfDemo {
public static void main(String[] args) {
List<string> list = new ArrayList();
list.add("A");
list.add("B");
list.add("C");
// 使用 removeIf 安全过滤
list.removeIf(item -> item.equals("A"));
System.out.println(list); // 输出 [B, C]
}
}</string>
执行 removeIf 后,列表变为 [B, C]。这种方法代码更简洁,且避免了手动管理迭代器的复杂性。它在底层实现上通常也是安全的,适合用于基于条件的批量删除操作。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











