杰瑞科技汇

Java for循环遍历List集合有哪些方式?

假设我们有以下 List 作为示例数据:

Java for循环遍历List集合有哪些方式?-图1
(图片来源网络,侵删)
import java.util.Arrays;
import java.util.List;
List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry", "Date");

经典的 for 循环 (索引遍历)

这是最传统、最基础的方式,通过索引来访问 List 中的每一个元素。

语法

for (int i = 0; i < list.size(); i++) {
    // 通过 list.get(i) 获取元素
    Element element = list.get(i);
    // ... 操作元素
}

示例代码

System.out.println("--- 方法一:经典 for 循环 (索引遍历) ---");
for (int i = 0; i < fruits.size(); i++) {
    String fruit = fruits.get(i);
    System.out.println("水果: " + fruit);
}

优点

  1. 直观易懂:对于初学者来说最容易理解。
  2. 灵活性高:可以在遍历过程中方便地获取元素的索引 i,可以轻松地访问前一个或后一个元素(list.get(i-1))。
  3. 性能:对于 ArrayListget(i) 操作是 O(1) 时间复杂度,因此整体性能非常好。

缺点

  1. 代码冗长:需要手动管理索引变量 i,代码看起来比较啰嗦。
  2. 不适用于所有 List 实现:对于 LinkedListget(i) 操作需要遍历链表,时间复杂度为 O(n),会导致整个循环的性能下降到 O(n²)。此方法只推荐用于 ArrayList 及其类似基于数组的列表

增强 for 循环 (for-each 循环)

这是 Java 5 引入的语法糖,专门用于遍历集合和数组,是目前最推荐、最常用的方式。

语法

for (Element element : list) {
    // element 就是当前遍历到的元素
    // ... 操作元素
}

示例代码

System.out.println("\n--- 方法二:增强 for 循环 (for-each) ---");
for (String fruit : fruits) {
    System.out.println("水果: " + fruit);
}

优点

  1. 代码简洁:语法非常简洁,可读性高。
  2. 安全性高:不会出现数组越界等索引相关的错误。
  3. 通用性强:适用于所有实现了 Iterable 接口的集合(包括 ArrayList, LinkedList, HashSet 等),性能稳定。

缺点

  1. 无法获取索引:如果遍历过程中需要知道当前元素的索引,此方法无能为力。
  2. 无法修改集合本身:在遍历过程中,不能直接添加或删除集合中的元素(会抛出 ConcurrentModificationException 异常),如果需要修改,必须使用迭代器(见方法三)。

使用 Iterator (迭代器)

Iterator 是集合框架的一部分,它提供了一种标准的方式来遍历集合,并且允许在遍历过程中安全地删除元素。

语法

Iterator<Element> iterator = list.iterator();
while (iterator.hasNext()) {
    Element element = iterator.next();
    // ... 操作元素
    // 如果需要删除当前元素,必须使用 iterator.remove()
    // list.remove(element); // 错误!会导致并发修改异常
    // iterator.remove(); // 正确!
}

示例代码

System.out.println("\n--- 方法三:使用 Iterator ---");
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
    String fruit = iterator.next();
    System.out.println("水果: " + fruit);
}

优点

  1. 安全删除元素:这是 Iterator 最核心的优势,在遍历过程中,只能通过 iterator.remove() 方法来删除刚刚由 next() 返回的元素,这样可以避免 ConcurrentModificationException
  2. 通用性强:和 for-each 一样,适用于所有集合。

缺点

  1. 代码稍显复杂:相比 for-each 循环,代码要多几行。
  2. 无法获取索引:同样无法直接获取元素的索引。

Java 8+ 中的 forEach 方法

Iterator 也可以结合 Java 8 的 Lambda 表达式使用,使代码更简洁:

Java for循环遍历List集合有哪些方式?-图2
(图片来源网络,侵删)
System.out.println("\n--- 方法三 (Java 8+): Iterator + forEach ---");
fruits.iterator().forEachRemaining(fruit -> {
    System.out.println("水果: " + fruit);
});

Java 8+ Stream API (流式处理)

对于复杂的集合操作(如过滤、映射、聚合),Stream API 提供了非常强大和声明式的方式,虽然它不完全是 for 循环,但也是遍历和处理集合的现代标准。

示例代码

System.out.println("\n--- 方法四:Java 8+ Stream API ---");
// 1. 简单遍历
fruits.stream().forEach(fruit -> {
    System.out.println("水果: " + fruit);
});
// 2. 带条件的遍历(只打印长度大于 5 的水果)
System.out.println("\n--- 只打印长度大于 5 的水果 ---");
fruits.stream()
      .filter(fruit -> fruit.length() > 5) // 过滤
      .forEach(fruit -> System.out.println("水果: " + fruit)); // 遍历

优点

  1. 声明式编程:你只需要“声明”你想做什么(如“过滤”、“排序”),而不需要关心“怎么做”,代码更易读。
  2. 功能强大:可以轻松进行链式操作,组合多种复杂的处理逻辑。
  3. 并行处理:只需将 stream() 换成 parallelStream(),即可轻松实现并行计算,提升大数据集的处理效率。

缺点

  1. 性能开销:对于简单的遍历,Stream API 会比传统的 for 循环有轻微的性能开销(因为涉及函数调用和流对象创建)。
  2. 学习曲线:对于初学者,理解函数式概念(如 filter, map, lambda)需要时间。

总结与最佳实践

方法 优点 缺点 适用场景
经典 for 循环 直观,可获取索引,ArrayList 性能好 代码冗长,LinkedList 性能差 仅用于 ArrayList,且需要索引时。
增强 for 循环 (for-each) 代码简洁,可读性高,安全通用 无法获取索引,遍历中不能修改集合 绝大多数遍历场景的首选,尤其是只读遍历。
Iterator 唯一能在遍历中安全删除元素的方式 代码稍复杂,无法获取索引 需要在遍历过程中删除元素时。
Stream API 功能强大,声明式,易于并行化 简单遍历有开销,学习曲线陡 需要进行复杂的数据处理(过滤、映射、聚合等)。

如何选择?

  1. 日常遍历,只读操作直接使用 for-each 循环,这是最常见、最安全、最简洁的选择。

    for (String fruit : fruits) {
        // ...
    }
  2. 遍历 ArrayList 且需要索引:可以使用经典 for 循环

    for (int i = 0; i < fruits.size(); i++) {
        String fruit = fruits.get(i);
        // ... 使用 i
    }
  3. 需要在遍历中删除元素必须使用 Iterator

    Java for循环遍历List集合有哪些方式?-图3
    (图片来源网络,侵删)
    Iterator<String> iterator = fruits.iterator();
    while (iterator.hasNext()) {
        String fruit = iterator.next();
        if (shouldRemove(fruit)) {
            iterator.remove(); // 安全删除
        }
    }
  4. 需要进行复杂的数据处理(过滤、转换等):使用 Stream API

    List<String> longFruits = fruits.stream()
                                   .filter(f -> f.length() > 5)
                                   .collect(Collectors.toList());
分享:
扫描分享到社交APP
上一篇
下一篇