Java Iterator安全遍历需严格遵循三步:先hasNext()判断、再next()获取元素、仅在next()后立即remove();否则抛IllegalStateException;for-each中直接删元素会触发fail-fast机制抛ConcurrentModificationException。

Java Iterator 实现安全遍历,核心在于三点:用 hasNext() 控制循环边界、用 next() 获取元素、用 remove() 替代集合自身的删除操作。它不是“更高级的for循环”,而是通过解耦遍历逻辑与数据结构,从机制上避免并发修改异常。
安全遍历的三步固定写法
所有标准集合(ArrayList、LinkedList、HashSet 等)都实现了 Iterable 接口,因此都能调用 iterator() 方法获取迭代器。安全遍历必须严格按以下顺序执行:
- 先调用 hasNext() 判断是否还有元素——返回 true 才能继续
- 再调用 next() 取出当前元素并自动移动指针
- 如需删除,只能在刚调用完 next() 后,立即调用一次 remove()
为什么不能在 for-each 里删元素
增强 for 循环(for (String s : list))底层就是 Iterator,但它隐藏了 next() 和 remove() 的调用时机。一旦你在循环体里直接调用 list.remove(s),集合的 modCount 就会变化,而迭代器内部的 expectedModCount 没同步更新,下一次检查就会抛 ConcurrentModificationException。
这不是语法限制,是 fail-fast 机制的主动保护——它宁可报错,也不让遍历结果不可靠。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
删除操作的合法时机与常见错误
remove() 不是独立可用的方法,它的行为完全依赖于上一次 next() 的执行状态:
- ✅ 正确:调用一次 next() → 立即调用一次 remove()
- ❌ 错误:还没调用 next() 就调 remove() → 抛 IllegalStateException
- ❌ 错误:连续两次调 remove()(中间没穿插 next())→ 同样抛 IllegalStateException
多线程环境下的注意事项
标准 Iterator 是 fail-fast 的,不适用于多线程同时读写同一集合。如果必须在并发场景使用:
- 改用线程安全集合,例如 CopyOnWriteArrayList,它的 Iterator 是 fail-safe(不会抛 CME)
- 或对整个遍历块加 synchronized,但会牺牲性能
- 不建议手动同步 Iterator 对象本身——它只是个轻量游标,同步它没意义

















