避免ConcurrentModificationException须用Iterator.remove()或removeIf();倒序for适用于List删除;高读低写并发场景可用CopyOnWriteArrayList。

Java 集合遍历时避免 ConcurrentModificationException,核心是**不通过集合自身删除元素,只用 Iterator.remove()**。这个异常不是多线程专属,单线程下直接在 for-each 或普通 for 循环里调用 list.remove() 同样会触发。
必须用 Iterator.remove() 删除当前元素
这是最标准、最通用的解法,适用于所有实现了 Iterator 的集合(ArrayList、LinkedList、HashSet 等)。
-
只能在
next()调用之后立即调用,否则抛IllegalStateException -
每次
next()后最多调一次remove(),不能连删 - 不能在
hasNext()前调用,也不能在循环末尾多调一次
示例:
List<string> list = new ArrayList(Arrays.asList("a", "b", "c", "b"));
Iterator<string> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("b".equals(s)) {
it.remove(); // ✅ 安全且合法
}
}
// 结果:["a", "c"]
</string></string>
Java 8+ 推荐用 removeIf() 一行解决
这是对 Iterator.remove() 的封装,语义更清晰,底层仍走安全迭代逻辑,适合条件筛选删除。
- 所有标准集合(
ArrayList、HashSet、LinkedHashSet等)都支持 - 写法简洁:
list.removeIf(s -> "b".equals(s)); - 无需手动管理迭代器,不易出错
仅限 List:倒序 for 循环删除
利用索引从大到小遍历,删除末尾元素不影响前面元素位置,规避下标错位问题。
- 只适用于
List实现类(ArrayList、LinkedList),Set和Map不可用 - 删除后无需调整索引,比正序循环中
i--更直观可靠
示例:
for (int i = list.size() - 1; i >= 0; i--) {
if ("b".equals(list.get(i))) {
list.remove(i); // ✅ 安全(因倒序)
}
}
读多写少的并发场景:换用 CopyOnWriteArrayList
它的迭代器基于快照,遍历时修改原集合不会影响当前迭代过程,天然规避该异常。
- 适合多线程下频繁读 + 偶尔写(如监听器列表、配置白名单)
- 写操作(
add/remove)会复制整个数组,内存和 CPU 开销大 - 不适用于写操作密集或集合很大的场景
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











