Iterator 是 Java 集合框架中非常重要的一个接口,它提供了一种统一的方式来遍历集合(如 List, Set 等)中的元素,而无需关心集合底层的具体实现。

什么是 Iterator?
Iterator 是一个接口,它定义了在集合上进行迭代操作的基本方法,你可以把它想象成一个“游标”或者“指针”,它指向集合中的某个元素,并允许你逐个访问这些元素。
Iterator 接口主要包含以下三个方法:
| 方法 | 描述 |
|---|---|
boolean hasNext() |
判断集合中是否还有下一个元素可以迭代,如果返回 true,说明调用 next() 是安全的。 |
E next() |
返回迭代的下一个元素,并将游标向后移动一位。注意: 如果没有下一个元素,会抛出 NoSuchElementException 异常。 |
void remove() |
从集合中移除由 next() 方法返回的最后一个元素。注意: 这个方法是可选的,如果集合不支持该操作,会抛出 UnsupportedOperationException 异常,通常在 next() 调用之后立即调用一次,且不能连续调用。 |
如何获取 Iterator?
任何实现了 Collection 接口的集合类,都提供了一个 iterator() 方法,用于获取该集合的迭代器。
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// 获取迭代器
Iterator<String> iterator = list.iterator();
Iterator 的标准遍历方式
这是最基本、最推荐的 Iterator 遍历方式,它清晰、安全且高效。

语法结构:
// 1. 获取迭代器
Iterator<T> iterator = collection.iterator();
// 2. 使用 while 循环进行遍历
while (iterator.hasNext()) {
// 3. 获取下一个元素
T element = iterator.next();
// 4. 对元素进行操作
System.out.println(element);
}
完整示例代码:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
fruits.add("Date");
System.out.println("使用 Iterator 标准方式遍历:");
// 1. 获取迭代器
Iterator<String> iterator = fruits.iterator();
// 2. 使用 while 循环
while (iterator.hasNext()) {
// 3. 获取元素
String fruit = iterator.next();
System.out.println(fruit);
// 示例:如果元素是 "Banana",就将其移除
if ("Banana".equals(fruit)) {
// 4. 使用迭代器安全地移除元素
iterator.remove();
}
}
System.out.println("\n移除 'Banana' 后的集合内容: " + fruits);
}
}
输出:
使用 Iterator 标准方式遍历:
Apple
Banana
Cherry
Date
移除 'Banana' 后的集合内容: [Apple, Cherry, Date]
关键点:

hasNext():在调用next()之前,务必检查hasNext(),以避免NoSuchElementException。iterator.remove():这是Iterator最强大的功能之一,它可以在遍历时安全地移除元素,而不会破坏迭代过程。绝对不要在迭代时使用集合自身的remove()方法(如list.remove("Banana")),这可能会导致ConcurrentModificationException(并发修改异常)。
Iterator 的其他遍历方式
虽然 while 循环是标准,但 Iterator 本身也可以用于 for-each 循环(增强 for 循环)。
for-each 循环
for-each 循环是 Java 5 引入的语法糖,它在底层就是通过 Iterator 实现的,所以使用 for-each 遍历集合和使用 Iterator 遍历在本质上是一样的。
语法结构:
for (T element : collection) {
// 对 element 进行操作
System.out.println(element);
}
完整示例代码:
import java.util.ArrayList;
import java.util.List;
public class ForEachExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
System.out.println("使用 for-each 循环遍历:");
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}
输出:
使用 for-each 循环遍历:
Apple
Banana
Cherry
重要区别:
for-each 循环非常简洁,但它有一个限制:你无法在遍历过程中使用 Iterator 的 remove() 方法来移除元素。 编译器会报错,因为 for-each 隐藏了迭代器对象。
如果你需要在遍历时修改集合(删除或添加元素),必须使用显式的 while(iterator.hasNext()) 循环。
Iterator vs. ListIterator
ListIterator 是 Iterator 的一个子接口,专门为 List 接口设计,它提供了比 Iterator 更强大的功能:
| 特性 | Iterator |
ListIterator |
|---|---|---|
| 适用范围 | 所有 Collection |
仅 List |
| 遍历方向 | 只能向后 | 可以向前和向后 |
| 添加元素 | 不支持 | add(E e) |
| 获取索引 | 不支持 | nextIndex(), previousIndex() |
| 移除元素 | remove() 移除上一个 next() 的元素 |
remove() 移除上一个 next() 或 previous() 的元素 |
| 修改元素 | 不支持 | set(E e) 修改上一个 next() 或 previous() 的元素 |
ListIterator 示例:
import java.util.ArrayList;
import java.util.ListIterator;
public class ListIteratorExample {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
ListIterator<String> listIterator = list.listIterator();
System.out.println("向后遍历:");
while (listIterator.hasNext()) {
System.out.println(listIterator.next());
}
System.out.println("\n向前遍历:");
while (listIterator.hasPrevious()) {
System.out.println(listIterator.previous());
}
// 修改元素
listIterator = list.listIterator(); // 重置迭代器
if (listIterator.hasNext()) {
listIterator.next(); // 移动到 "B"
listIterator.set("Z"); // 将 "B" 修改为 "Z"
}
System.out.println("\n修改后的集合: " + list);
}
}
输出:
向后遍历:
A
B
C
向前遍历:
C
B
A
修改后的集合: [A, Z, C]
Java 8 中的 Iterator:forEachRemaining
Java 8 为 Iterator 接口添加了一个新的默认方法 forEachRemaining(Consumer<? super E> action),它允许你使用 Lambda 表达式来简化遍历。
语法结构:
iterator.forEachRemaining(element -> {
// 对 element 进行操作
System.out.println(element);
});
或者更简洁地:
iterator.forEachRemaining(System.out::println);
完整示例代码:
import java.util.ArrayList;
import java.util.Iterator;
public class ForEachRemainingExample {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
Iterator<Integer> iterator = numbers.iterator();
System.out.println("使用 forEachRemaining 遍历:");
iterator.forEachRemaining(System.out::println);
}
}
输出:
使用 forEachRemaining 遍历:
10
20
30
总结与最佳实践
| 遍历方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
while (iterator.hasNext()) |
最灵活,可以在遍历时安全地使用 iterator.remove() 和 iterator.add() (如果是 ListIterator)。 |
代码稍显冗长。 | 需要遍历并修改集合时(特别是删除元素),这是最安全和推荐的方式。 |
for-each 循环 |
代码简洁易读,是日常遍历的首选。 | 无法在遍历过程中修改集合(会抛出异常)。 | 只读遍历,不需要在循环中添加或删除元素。 |
iterator.forEachRemaining() |
代码简洁,结合 Lambda 表达式非常优雅。 | 无法在遍历过程中修改集合。 | 只读遍历,且代码风格偏向函数式编程。 |
核心建议:
- 如果只需要遍历集合,使用
for-each循环,它最简洁、最易读。 - 如果需要在遍历时删除或添加元素,必须使用
while(iterator.hasNext())循环,并调用迭代器自身的remove()或add()方法。 - 如果需要双向遍历或修改/添加元素,请使用
ListIterator。
