← 返回题目列表

使用迭代器模式有哪些常见误区?

高频 中等 第 9 / 25 题 更新于 2026/07/28
迭代器模式误区Java集合

简化版

迭代器模式常见误区包括:把迭代器和集合混成一个对象、遍历时直接修改集合、以为 fail-fast 等于线程安全、忘记 next() 越界要抛异常、把所有简单循环都强行抽成迭代器。

详细版

迭代器模式的关键是“遍历状态独立于集合”。如果集合自己保存全局游标,多个遍历过程会互相干扰。

常见错误有:

  • 集合自己实现迭代器并保存唯一游标。
  • 增强 for 中调用集合 remove()
  • 认为 ConcurrentModificationException 能保证并发安全。
  • next() 没有元素时返回 null
  • 对简单固定遍历过度设计。
  • 迭代器暴露过多集合内部结构。

这些问题本质上都破坏了迭代器的职责边界或使用约定。

完整版教学

一、误区一:集合自己保存遍历游标

如果集合内部只有一个游标,那么同一个集合同时遍历两次就会出问题。

例如:

Iterator<String> it1 = list.iterator();
Iterator<String> it2 = list.iterator();

如果 it1it2 实际共享同一个游标,两个遍历过程就会互相影响。

正确做法是每次调用 iterator() 返回新的迭代器对象,每个迭代器保存自己的状态。

二、误区二:遍历时直接修改集合

增强 for 背后使用迭代器。如果循环中直接调用集合的 remove(),容易触发 fail-fast。

不推荐:

for (String s : list) {
    if (s.startsWith("A")) {
        list.remove(s);
    }
}

推荐:

Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    if (s.startsWith("A")) {
        it.remove();
    }
}

或者使用 removeIf(),让集合自己处理遍历删除。

三、误区三:认为 fail-fast 保证线程安全

fail-fast 只是检测到结构性修改时尽快抛异常,不是同步机制。

它不保证:

  • 一定能检测到所有并发修改。
  • 数据在并发环境中一定一致。
  • 多线程访问一定安全。

需要线程安全时,应使用并发集合、同步包装或显式锁。

四、误区四:next 越界返回 null

Iterator.next() 在没有元素时应该抛出 NoSuchElementException

如果返回 null,调用方无法判断是集合中真的有 null,还是已经遍历结束。

这会让错误被隐藏,后续更难排查。

五、误区五:迭代器泄露内部结构

迭代器应该提供遍历能力,而不是把底层数组、链表节点直接暴露出去。

如果迭代器返回内部节点对象,客户端仍然可能依赖集合实现细节。这样就没有达到封装目的。

六、误区六:所有循环都抽成迭代器

如果只是一个局部数组循环,没有复用需求,也不涉及封装内部结构,普通 for 循环就很好。

迭代器模式适合稳定抽象和复用遍历逻辑,不适合为了模式而制造额外层次。

七、常见误区与追问

迭代器错误通常集中在游标契约与并发修改。含3个元素的集合,合法调用序列应是 hasNext -> next 重复3次,第4次 next 必须抛 NoSuchElementException,不能返回 null 混淆真实空元素。删除操作也必须定义是否只能在成功 next 后调用一次。

检查维度判定依据
遍历结束hasNext=falsenext 抛异常
删除契约只删除最近一次返回的元素
cursor: 0 -> 1 -> 2 -> 3(end)

易错点:Iterator 是有状态游标,同一个实例不能当作可重复遍历的集合。

  • 误区:next 在末尾返回 null 更友好。 集合可能合法包含 null,标准契约用异常区分越界。
  • 追问:为什么每次 foreach 都能重新遍历? Iterable 每次调用 iterator() 应创建新的游标实例。
  • 误区:遍历时可直接调用集合 remove。 这会绕过迭代器状态并可能触发并发修改检测。
  • 追问:remove 连续调用两次会怎样? 标准 Iterator 契约通常抛 IllegalStateException
  • 追问:空集合怎么测试? 首次 hasNext 为 false,首次 next 就抛 NoSuchElementException

八、加强记忆

迭代器模式最容易错在“边遍历边乱改”和“游标放错地方”。记住:游标属于迭代器,结构属于集合;修改集合要遵守迭代器约定,fail-fast 只是提醒,不是并发安全护身符。