Java Iterator(迭代器)

更新于 2025-12-26

Jakob Jenkov 2020-05-22

Java 的 Iterator 接口表示一个能够遍历集合中对象的对象,一次遍历一个对象。Iterator 接口是 Java 中用于遍历集合的最古老机制之一(尽管不是最早的 —— 在它之前还有 Enumerator)。

要使用 Java Iterator,你需要从你想要遍历的对象集合中获取一个 Iterator 实例。所获得的 Iterator 会跟踪底层集合中的元素,以确保你遍历完所有元素。如果你在通过指向该集合的 Iterator 进行遍历时修改了底层集合,Iterator 通常会检测到这一点,并在你下次尝试从 Iterator 获取下一个元素时抛出异常。稍后将对此进行更详细的说明。

Java Iterator 核心方法

Java Iterator 接口相当简单。其核心方法如下:

方法 描述
hasNext() 如果 Iterator 还有更多元素,则返回 true;否则返回 false
next() 返回 Iterator 的下一个元素。
remove() 从 Iterator 所遍历的集合中移除最近由 next() 返回的元素。
forEachRemaining() 遍历 Iterator 中剩余的所有元素,并对每个元素调用传入的 Java Lambda 表达式

以下各节将分别介绍这些方法。


获取 Iterator

大多数情况下,你会通过从包含多个嵌套对象的 Java 对象中获取 Iterator 来使用它。标准 Java 集合接口 Collection 包含一个名为 iterator() 的方法。通过调用 iterator(),你可以从给定的 Collection 中获取一个 Iterator。

你也可以从许多 Java 集合数据结构(例如 ListSetMapQueueDeque 等)中获取 Iterator

以下是从各种 Java 集合类型中获取 Java Iterator 的几个示例:

List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
Iterator<String> iterator = list.iterator();

Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("three");
Iterator<String> iterator2 = set.iterator();

遍历 Iterator

你可以使用 while 循环来遍历 Iterator 中的对象。下面是一个使用 while 循环遍历 Java Iterator 元素的示例:

Iterator iterator = list.iterator();
while(iterator.hasNext()) {
    Object nextObject = iterator.next();
}

上面的 Java 示例中有两个方法需要注意:

  • 第一个是 IteratorhasNext() 方法,如果 Iterator 还有更多元素则返回 true。换句话说,如果 Iterator 尚未遍历完它所来源集合中的所有元素,hasNext() 就会返回 true;如果已经遍历完所有元素,则返回 false
  • 第二个是 next() 方法,它返回 Iterator 正在遍历的集合中的下一个元素。

遍历顺序

Java Iterator 中元素的遍历顺序取决于提供该 Iterator 的对象。例如,从 List 获取的 Iterator 会按照 List 内部存储元素的顺序进行遍历。而从 Set 获取的 Iterator 则不保证元素的遍历顺序。


Java List Iterator

以下是从 List 实例获取 Java Iterator 的示例:

List list = new ArrayList();
list.add("123");
list.add("456");
list.add("789");
Iterator iterator = list.iterator();

Java Set Iterator

以下是从 Set 实例获取 Java Iterator 的示例:

Set set = new HashSet();
set.add("123");
set.add("456");
set.add("789");
Iterator iterator = set.iterator();

遍历期间的修改

某些集合不允许你在通过 Iterator 遍历时修改集合。在这种情况下,当你下一次调用 Iteratornext() 方法时,会抛出 ConcurrentModificationException。以下示例在执行时会抛出 ConcurrentModificationException

List<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");

Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
    String value = iterator.next();
    if(value.equals("456")){
        list.add("999"); // 抛出 ConcurrentModificationException
    }
}

之所以抛出 ConcurrentModificationException,是因为如果你在通过 Iterator 遍历集合的同时修改了集合,Iterator 就会与集合不同步。


遍历期间删除元素

Java Iterator 接口提供了一个 remove() 方法,允许你从底层集合中删除刚刚由 next() 返回的元素。调用 remove() 不会导致抛出 ConcurrentModificationException。以下是在遍历 Iterator 时从集合中删除元素的示例:

List<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");

Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
    String value = iterator.next();
    if(value.equals("456")){
        iterator.remove(); // 安全删除
    }
}

forEachRemaining()

Java Iterator 的 forEachRemaining() 方法可以内部遍历 Iterator 中剩余的所有元素,并对每个元素调用作为参数传入的 Java Lambda 表达式。以下是使用 forEachRemaining() 的示例:

List<String> list = new ArrayList<>();
list.add("Jane");
list.add("Heidi");
list.add("Hannah");

Iterator<String> iterator = list.iterator();
iterator.forEachRemaining((element) -> {
    System.out.println(element);
});

ListIterator

Java 还包含一个名为 ListIterator 的接口,它扩展了 Iterator 接口。ListIterator 表示一个双向迭代器,即你可以向前和向后遍历元素。这里不会详细介绍 ListIterator 接口,但会展示一个快速使用示例:

List<String> list = new ArrayList<>();
list.add("Jane");
list.add("Heidi");
list.add("Hannah");

ListIterator<String> listIterator = list.listIterator();

while(listIterator.hasNext()) {
    System.out.println(listIterator.next());
}

while(listIterator.hasPrevious()) {
    System.out.println(listIterator.previous());
}

如你所见,该示例首先通过所有元素正向遍历 ListIterator,然后再反向遍历回第一个元素。


在自定义类中实现 Iterator 接口

如果你有一个特殊的、自定义的集合类型,你可以自己实现 Java Iterator 接口,以创建一个能遍历你自定义集合元素的 Iterator。本节将展示一个非常简单的 Java Iterator 接口自定义实现,让你了解如何自行实现 Iterator 接口。

我将为一个标准的 Java List 实现一个 Iterator。这个实现并不完美(例如,它无法检测遍历过程中 List 内容的变更),但足以让你了解 Iterator 实现的大致样子:

import java.util.Iterator;
import java.util.List;

public class ListIterator<T> implements Iterator<T> {
    private List<T> source = null;
    private int index = 0;

    public ListIterator(List<T> source){
        this.source = source;
    }

    @Override
    public boolean hasNext() {
        return this.index < this.source.size();
    }

    @Override
    public T next() {
        return this.source.get(this.index++);
    }
}

以下是使用上述 ListIterator 进行遍历的示例:

import java.util.ArrayList;
import java.util.List;

public class ListIteratorExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList();
        list.add("one");
        list.add("two");
        list.add("three");

        ListIterator<String> iterator = new ListIterator<>(list);
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}