ArrayList中高效使用Iterator的核心是安全可控而非提速,需用iterator.remove()删除元素、避免并发修改异常,多线程下应选用CopyOnWriteArrayList等替代方案。

在 ArrayList 中高效使用 Iterator,关键不是“快”,而是“安全+可控+不踩坑”。它本身不提速,但能帮你避开并发修改异常、误删元素、遍历中断等典型问题。
明确 Iterator 的适用边界
Iterator 适合需要边遍历边做条件判断或选择性删除的场景,比如过滤偶数、清理过期对象。如果只是顺序打印或只读访问,用增强 for 循环更简洁;如果要按索引操作,直接 get(i) 更直观。
- 必须用 Iterator.remove() 删除当前元素,绝不能调用 list.remove(item) 或 list.remove(index),否则触发 ConcurrentModificationException
- remove() 只能紧跟在一次 next() 之后调用,且每调用一次 next() 后最多调用一次 remove()
- 遍历中不能插入新元素(ArrayList 不支持迭代时 add),否则同样抛异常
避免 fail-fast 的实际写法
单线程下 fail-fast 很少出现,但一旦发生,基本是误用了 remove 方法或在遍历时手动改了集合。正确写法示例:
- 先调用 iterator.next() 获取元素
- 根据业务逻辑判断是否要删(如 item == null 或满足某条件)
- 满足则立即调用 iterator.remove(),不要跨循环体、不要重复调用
错误示范:list.remove(item)、iterator.remove(); iterator.remove();、next() 之前就 remove()
立即学习“Java免费学习笔记(深入)”;
多线程环境下的替代方案
ArrayList 本身非线程安全,Iterator 在多线程中天然不兼容。真要并发遍历,别硬扛,换思路:
- 读多写少 → 用 CopyOnWriteArrayList,它的 Iterator 不检查 modCount,遍历时写操作不影响当前快照
- 需强一致性且写操作频繁 → 改用 synchronized 包裹整个遍历块,锁住 list 对象
- 只读批量处理 → 先 new ArrayList(original) 做快照,再在副本上无锁遍历
- 数据量大、逻辑独立 → 考虑分片 + parallelStream(),但注意流中避免修改共享状态
性能与可读性的平衡建议
Iterator 比 for-i 略慢(有对象创建和方法调用开销),但差距微乎其微,不必为此放弃安全性。真正影响效率的是滥用 remove 导致的数组移动,或在循环里反复调用 size()、get()。
- 删除多个元素时,优先考虑收集待删索引,遍历完统一倒序删除,减少移动次数
- 避免在 hasNext() 或 next() 调用中嵌套耗时操作(如远程调用、IO)
- 若逻辑复杂,把判断抽成独立方法,保持 while 循环体干净


















