java中避免concurrentmodificationexception的关键是严格遵守迭代器修改契约:遍历时删除必须用iterator.remove(),且每个next()后至多调用一次remove();错误做法包括hasnext()前remove、连续两次remove或调用集合自身增删方法;需替换或插入时应改用listiterator;list可倒序for循环删除;多线程下需用copyonwritearraylist、concurrenthashmap或加锁。

Java 中 Iterator 避免并发修改异常(ConcurrentModificationException)的关键不是“怎么写 while 循环”,而是**严格遵守迭代器的修改契约**:遍历时若要删元素,必须用 iterator.remove(),且不能穿插集合自身的增删操作。
只用 iterator.remove() 删除当前元素
这是单线程下最直接、最安全的方式。每次 next() 返回一个元素后,可立即调用一次 remove() 删除它,迭代器会自动同步内部状态(更新 expectedModCount),避免下一次 hasNext() 检查失败。
- ✅ 正确:先
next(),再remove();每个next()最多配一个remove() - ❌ 错误:在
hasNext()前调用remove()(尚未定位元素) - ❌ 错误:连续两次调用
remove()(抛IllegalStateException) - ❌ 错误:在循环中调用
list.remove(obj)或list.add()
需要替换、插入或双向操作?换 ListIterator
Iterator 只支持删除;若需修改当前元素(set())、在当前位置后插入(add())或反向遍历,应改用 ListIterator:
- 调用
next()后可用set()替换当前元素、add()插入新元素 - 调用
previous()后也可用set()或add() - 仍禁止直接调用底层
list的结构修改方法
不想用迭代器?试试倒序 for 循环
对 List,用索引从大到小遍历,删除时不会影响未处理元素的位置,完全绕开迭代器机制:
- ✅ 安全:用
list.remove(i),不依赖Iterator - ✅ 简洁:逻辑清晰,无需额外对象
- ⚠️ 注意:仅适用于
List实现(如ArrayList、LinkedList),不通用
多线程环境下必须额外防护
即使用了 iterator.remove(),多个线程同时读写同一集合仍会触发异常。此时需升级方案:
- 读多写少 → 用
CopyOnWriteArrayList:迭代器基于快照,不抛异常,但写操作开销大 - 高并发 Map → 用
ConcurrentHashMap:其迭代器是弱一致性的,允许并发修改 - 可控场景 → 加锁:所有访问(包括
iterator()和remove())都包裹在synchronized(list)中
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











