Iterable 接口仅定义 iterator() 方法以标准化遍历入口,真正遍历由 Iterator 实例执行;Iterator 封装单次遍历状态,通过 hasNext()、next()、remove() 三方法提供统一遍历契约,解耦客户端与集合内部结构。

Iterable 接口本身不参与遍历,它只承诺“我能给你一个 Iterator”。真正执行遍历动作的是 Iterator 实例,而 Iterable 的价值在于把“提供遍历能力”这件事标准化、解耦化。
Iterable 是集合的“遍历出口”,不是遍历本身
Iterable 接口只有一个核心方法:iterator()。它不定义怎么走、从哪开始、是否跳过元素——这些全部交给返回的 Iterator 对象去管。比如 ArrayList.iterator() 返回的是内部类 ArrayList.Itr,LinkedList 返回的是 LinkedLisItr,它们实现同一套接口,但内部逻辑完全不同。
- 调用
list.iterator()每次都应返回**新实例**,保证多次遍历互不影响 - for-each 循环(
for (String s : list))在编译期会被转成等效的 iterator 调用,底层完全依赖 Iterable.iterator() + Iterator.hasNext()/next() - 自定义类想支持 for-each,只需实现 Iterable
,并在 iterator() 中返回一个状态正确、游标独立的 Iterator 实现
Iterator 封装了“一次遍历”的全部状态
Iterator 不是工具类,而是一个有状态的对象:它记住当前走到哪、下一个是否存在、上一个取过没。它的三个关键方法构成最小完备协议:
- hasNext():查“还有没有下一站”,不移动指针
- next():走到下一站,并把站牌上的元素交给你;调用后游标前移
- remove()(可选):删掉刚刚由 next() 返回的那个元素;必须紧跟 next() 后调用,否则抛 IllegalStateException
一旦遍历结束或中途异常,该 Iterator 实例通常就失效了——再调 next() 多数会抛 NoSuchElementException,它不是设计来复用的。
统一遍历的关键,在于“客户端不碰集合结构”
没有 Iterator 模式时,遍历 ArrayList 要靠索引 get(i),遍历 LinkedList 却得顺着 next 指针跳。客户端代码和数据结构强绑定,换一种集合就得重写逻辑。
- 用了 Iterator 后,无论背后是数组、链表、红黑树还是自定义树形结构,客户端只认
hasNext()和next() - 集合类自己决定怎么实现 Iterator:正序、倒序、过滤、延迟计算……全在 iterator() 返回值里做文章
- Java 的 for-each、Stream.of().iterator()、甚至第三方库的分页迭代器,都基于这套契约协作
常见误区提醒
有些细节容易被忽略,却直接影响行为正确性:
- 认为“实现了 Iterable 就自动支持 for-each”——错。关键是
iterator()返回的 Iterator 是否维护了有效游标;返回 null 或单例共享实例会导致遍历失败 - 在多线程中直接共享同一个 Iterator 实例——危险。Iterator 不是线程安全的,应为每个线程分配独立实例
- 在遍历时用集合自身方法增删元素(如 list.remove(obj)),而非 iterator.remove()——大概率触发
ConcurrentModificationException

















