java中iterator遍历时仅允许调用其remove()删除刚next()获取的元素,否则抛concurrentmodificationexception;需批量操作则先收集后统一处理,或多线程下改用copyonwritearraylist等并发集合。

Java 中用 Iterator 遍历时修改集合,核心是“只允许用它自己的 remove() 方法删元素”,其他任何直接改集合的操作(比如 list.remove()、list.add())都会触发 ConcurrentModificationException。这不是 bug,而是 fail-fast 机制在保护数据一致性。
必须用 iterator.remove() 删除
调用 next() 取出一个元素后,立刻调用 remove() 是唯一安全的删除方式。这个 remove() 必须紧跟在本次 next() 之后,且不能重复调用。
- ✅ 正确:先
it.next(),再it.remove() - ❌ 错误:没调
next()就remove()→ 抛IllegalStateException - ❌ 错误:同一
next()后连续两次remove()→ 同样抛IllegalStateException - ❌ 错误:用
list.remove(obj)或list.remove(index)→ 抛ConcurrentModificationException
不能删、不能加、不能改?那就分两步走
Iterator 接口只提供 remove(),不支持 add()、set() 等操作。如果逻辑需要插入、替换或批量删多个不同条件的元素:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 先遍历收集要操作的元素(比如放进
List<string> toRemove</string>或Map<integer string> toUpdate</integer>) - 遍历结束后,统一调用
list.removeAll(toRemove)或逐个list.set(i, newValue) - 对
List场景,也可换用ListIterator—— 它支持add()、set()和双向遍历,但同样要求:必须在next()或previous()之后才能调对应修改方法
多线程环境下别硬扛,换并发集合
单线程里靠 iterator.remove() 能解决大部分问题;但多线程中,光靠迭代器无法规避竞争。这时应优先选用线程安全的替代方案:
-
CopyOnWriteArrayList:读多写少场景首选。遍历时操作原集合(如add()、remove())完全不会影响当前迭代,因为每次写都新建副本 -
ConcurrentHashMap:keySet()/values()/entrySet() 返回的迭代器是弱一致性的,不抛CME,适合高并发读写 - 实在要用普通集合 + 迭代器:必须对整个遍历块加锁(如
synchronized(list)),但要注意锁粒度,避免把耗时逻辑也包进去
增强 for 循环不支持安全删除
虽然 for (String s : list) 看起来简洁,但它底层仍是 Iterator,且屏蔽了 remove() 调用能力。一旦在循环体内执行 list.remove(s),100% 触发 ConcurrentModificationException。
- 需要边遍历边删 → 改用显式
Iterator+remove() - 只是过滤保留 → 优先考虑
list.removeIf(predicate)(Java 8+),它内部封装了安全迭代逻辑 - 复杂处理逻辑 → 用 Stream API(如
list.stream().filter(...).collect(...)),语义清晰且天然无 CME 风险
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










