Iterator 是 Java 集合框架中一个非常核心和基础的接口,它提供了一种统一的方式来遍历集合(Collection)中的元素,而无需关心集合底层的具体实现。

什么是 Iterator?
Iterator 的设计遵循了迭代器模式,它的核心思想是将遍历操作与集合本身分离。
想象一下,你去图书馆看书,如果你直接走进书库,自己一本本地找,这就像直接使用集合的 get(index) 方法(ArrayList),效率低下且逻辑混乱。
而更好的方式是,你向图书管理员(Iterator)借一个“书单”,然后按照书单的顺序一本一本地取书,你不需要关心书是按什么规则排列的(按作者、按分类还是按入库时间),你只需要按照书单(Iterator)的指示来操作即可。
Iterator 就扮演了这个“书单”的角色,它告诉你:

- 是否还有下一本书? (
hasNext()) - 请给我下一本书。 (
next()) - 我不想要这本书了,请把它放回原处。 (
remove())
Iterator 接口的核心方法
java.util.Iterator 接口定义了三个核心方法:
| 方法 | 描述 | 返回值 |
|---|---|---|
boolean hasNext() |
检查迭代中是否还有更多的元素,如果有,返回 true;否则返回 false。 |
boolean |
E next() |
返回迭代中的下一个元素。 | 元素类型 E |
default void remove() |
可选操作,从迭代器最后一次返回的元素集合中移除该元素,每次调用 next() 后只能调用一次 remove()。 |
void |
重要提示:
remove()是一个default方法(Java 8 引入),意味着Iterator接口提供了默认实现,但集合的具体实现类可以选择覆盖它,很多情况下,调用remove()方法会抛出UnsupportedOperationException。remove()方法是安全地在遍历过程中修改集合的方式,它会同步更新迭代器和集合的状态,避免ConcurrentModificationException(并发修改异常)。
如何获取和使用 Iterator?
几乎所有实现了 Collection 接口的类都提供了一个 iterator() 方法,用于返回一个该集合的 Iterator 对象。
基本使用示例
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorExample {
public static void main(String[] args) {
// 1. 创建一个 List 集合
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add("Mango");
System.out.println("原始集合: " + fruits);
// 2. 通过 iterator() 方法获取迭代器
Iterator<String> iterator = fruits.iterator();
// 3. 使用迭代器遍历集合
System.out.println("\n使用迭代器遍历集合:");
while (iterator.hasNext()) {
// 4. 获取下一个元素
String fruit = iterator.next();
System.out.println("当前水果: " + fruit);
// 5. 示例:移除 "Orange"
if ("Orange".equals(fruit)) {
System.out.println("发现 Orange,准备移除...");
iterator.remove(); // 安全地移除元素
}
}
System.out.println("\n移除 Orange 后的集合: " + fruits);
}
}
输出结果:

原始集合: [Apple, Banana, Orange, Mango]
使用迭代器遍历集合:
当前水果: Apple
当前水果: Banana
当前水果: Orange
发现 Orange,准备移除...
当前水果: Mango
移除 Orange 后的集合: [Apple, Banana, Mango]
代码解析:
- 我们创建了一个
ArrayList并添加了一些元素。 - 调用
fruits.iterator()获取了Iterator实例。 - 使用
while (iterator.hasNext())循环,这是标准的迭代器遍历模式,确保在尝试获取元素之前先检查是否存在。 iterator.next()获取元素并移动指针。- 当元素是 "Orange" 时,我们调用
iterator.remove(),这个方法会从底层的ArrayList中移除 "Orange",并且不会破坏迭代器的状态。
for-each 循环与 Iterator 的关系
你可能更熟悉 for-each 循环(增强 for 循环),它在代码上更简洁。
for (String fruit : fruits) {
System.out.println(fruit);
}
for-each 和 Iterator 是什么关系呢?
答案是:for-each 循环的内部实现就是 Iterator。
当你编译上面的 for-each 代码时,JVM 会将其转换成类似下面这样的基于 Iterator 的代码:
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
这意味着:
- 所有可以使用
for-each循环的类,都必须实现了Iterable接口。 Iterable接口中定义了一个iterator()方法,这正是for-each循环所需要的。
Iterable 接口定义:
public interface Iterable<T> {
Iterator<T> iterator(); // 返回一个迭代器
// ... 其他默认方法
}
for-each 循环会自动调用这个 iterator() 方法来获取迭代器,然后使用 hasNext() 和 next() 进行遍历。
Iterator vs. ListIterator
Iterator 有一个更强大的子接口——ListIterator,它专门用于遍历 List 集合。
| 特性 | Iterator |
ListIterator |
|---|---|---|
| 适用范围 | 所有 Collection |
仅 List |
| 遍历方向 | 单向(只能向后) | 双向(可以向前向后) |
| 额外方法 | hasNext(), next(), remove() |
hasNext(), next()<br>hasPrevious(), previous()<br>add(E e), set(E e)<br>nextIndex(), previousIndex() |
ListIterator 的优势:
- 双向遍历:可以使用
hasPrevious()和previous()从后向前遍历。 - 添加元素:
add(E e)方法可以在当前位置插入一个新元素。 - 修改元素:
set(E e)方法可以替换最后一次返回的元素。
Iterator 的注意事项
-
ConcurrentModificationException(并发修改异常)- 场景:当你使用
Iterator遍历一个集合时,如果不是通过iterator.remove()方法,而是通过集合自身的remove()方法(或其他修改集合结构的方法)来修改集合,就会抛出此异常。 - 原因:迭代器创建后,会维护一个“预期修改次数”(
expectedModCount),每次集合被结构性修改(增、删)时,modCount会自增,当迭代器执行next()或remove()时,它会检查expectedModCount是否等于modCount,如果不等,说明在迭代过程中集合被其他方式修改了,迭代器认为其状态已失效,于是抛出异常。 - 解决方案:如果需要在遍历时删除元素,务必使用
iterator.remove()。
- 场景:当你使用
-
NoSuchElementException- 场景:当
iterator.hasNext()返回false时,如果再调用iterator.next(),就会抛出此异常。 - 原因:表示已经到达集合的末尾,没有更多元素可以获取了。
- 场景:当
-
IllegalStateException- 场景:在不允许的情况下调用
remove()方法。 - 原因:通常发生在以下情况:
- 在调用
next()之前就调用了remove()。 - 在一次
next()调用后,连续调用了两次remove()。
- 在调用
- 场景:在不允许的情况下调用
| 特性 | 描述 |
|---|---|
| 核心作用 | 提供一种统一、安全的方式来遍历集合元素。 |
| 设计模式 | 迭代器模式,将遍历逻辑与集合实现解耦。 |
| 关键方法 | hasNext(), next(), remove()。 |
| 获取方式 | 通过集合的 iterator() 方法获得。 |
for-each 关系 |
for-each 循环是 Iterator 的语法糖,底层实现依赖 Iterable 接口。 |
| 安全删除 | 在遍历过程中删除元素,必须使用 iterator.remove()。 |
| 局限性 | Iterator 是单向的,对于 List,如果需要更强大的功能(如双向遍历、增删改),应使用 ListIterator。 |
掌握 Iterator 是理解 Java 集合框架的关键一步,它不仅是一种遍历工具,更体现了 Java 设计中“解耦”和“统一接口”的优秀思想。
