杰瑞科技汇

Java遍历Iterator的正确方式是什么?

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

Java遍历Iterator的正确方式是什么?-图1
(图片来源网络,侵删)

什么是 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 遍历方式,它清晰、安全且高效。

Java遍历Iterator的正确方式是什么?-图2
(图片来源网络,侵删)

语法结构:

// 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]

关键点:

Java遍历Iterator的正确方式是什么?-图3
(图片来源网络,侵删)
  • 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 循环非常简洁,但它有一个限制你无法在遍历过程中使用 Iteratorremove() 方法来移除元素。 编译器会报错,因为 for-each 隐藏了迭代器对象。

如果你需要在遍历时修改集合(删除或添加元素),必须使用显式的 while(iterator.hasNext()) 循环。


Iterator vs. ListIterator

ListIteratorIterator 的一个子接口,专门为 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 中的 IteratorforEachRemaining

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 表达式非常优雅。 无法在遍历过程中修改集合。 只读遍历,且代码风格偏向函数式编程。

核心建议:

  1. 如果只需要遍历集合,使用 for-each 循环,它最简洁、最易读。
  2. 如果需要在遍历时删除或添加元素,必须使用 while(iterator.hasNext()) 循环,并调用迭代器自身的 remove()add() 方法。
  3. 如果需要双向遍历或修改/添加元素,请使用 ListIterator
分享:
扫描分享到社交APP
上一篇
下一篇