我们将以一个 List<String> 为例进行演示:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListIterationExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date"));
// 我们将使用不同的方法遍历这个 fruits 列表
}
}
传统的 For 循环 (索引遍历)
这是最基础、最通用的遍历方式,适用于任何实现了 List 接口的集合。
特点:
- 通过索引(从 0 开始)来访问每个元素。
- 可以在遍历过程中方便地获取元素的索引。
- 如果需要在遍历时修改列表(例如删除元素),必须非常小心,否则容易抛出
IndexOutOfBoundsException或导致逻辑错误。
// fruits 列表: ["Apple", "Banana", "Cherry", "Date"]
System.out.println("--- 1. For 循环 (索引遍历) ---");
for (int i = 0; i < fruits.size(); i++) {
String fruit = fruits.get(i);
System.out.println("索引 " + i + ": " + fruit);
}
// 输出:
// 索引 0: Apple
// 索引 1: Banana
// 索引 2: Cherry
// 索引 3: Date
适用场景:
- 当你需要元素的索引时。
- 遍历数组时(数组没有
forEach方法)。 - 在某些旧版 Java 项目中。
增强 For 循环 (For-Each 循环)
这是 Java 5 引入的一种更简洁、更安全的遍历方式。

特点:
- 语法简洁,可读性高。
- 底层使用迭代器实现,可以避免索引越界的问题。
- 重要: 在使用增强 for 循环遍历集合时,不能直接修改集合的结构(如
add()或remove()),否则会抛出ConcurrentModificationException,如果需要修改,应使用迭代器的remove()方法。
// fruits 列表: ["Apple", "Banana", "Cherry", "Date"]
System.out.println("\n--- 2. 增强 For 循环 (For-Each) ---");
for (String fruit : fruits) {
System.out.println("水果: " + fruit);
}
// 输出:
// 水果: Apple
// 水果: Banana
// 水果: Cherry
// 水果: Date
适用场景:
- 这是最常用、最推荐的遍历方式,当只需要集合中的元素,而不需要索引时。
- 代码简洁,不易出错。
使用迭代器 (Iterator)
迭代器是 Java 集合框架的一部分,它提供了一种标准的方式来遍历集合,并且可以在遍历时安全地修改集合。
特点:

hasNext():检查是否还有下一个元素。next():获取下一个元素。remove():移除最近由next()返回的元素,这是在遍历时安全删除元素的标准方法。
// fruits 列表: ["Apple", "Banana", "Cherry", "Date"]
System.out.println("\n--- 3. 使用迭代器 (Iterator) ---");
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println("水果: " + fruit);
// 示例:移除 "Banana"
if ("Banana".equals(fruit)) {
iterator.remove(); // 安全地移除元素
}
}
System.out.println("移除 Banana 后的列表: " + fruits);
// 输出:
// 水果: Apple
// 水果: Banana
// 水果: Cherry
// 水果: Date
// 移除 Banana 后的列表: [Apple, Cherry, Date]
适用场景:
- 当你需要在遍历过程中添加、删除或修改集合中的元素时。
- 这是唯一一种可以在遍历时安全地修改集合结构的方式。
Java 8+ Stream API (流式处理)
这是 Java 8 引入的函数式编程特性,它提供了一种强大而灵活的方式来处理集合。
特点:
- 声明式:你只需告诉“做什么”,而不需要关心“怎么做”。
- 惰性求值:很多中间操作(如
filter,map)不会立即执行,只有遇到终端操作(如forEach,collect)时才会触发。 - 并行处理:可以轻松地切换到并行流,利用多核 CPU 提高处理速度。
// fruits 列表: ["Apple", "Banana", "Cherry", "Date"]
System.out.println("\n--- 4. 使用 Stream API ---");
// 4.1 forEach 遍历
System.out.println("--- 4.1 Stream.forEach ---");
fruits.stream().forEach(fruit -> System.out.println("水果: " + fruit));
// 4.2 结合 filter 和 forEach 进行条件遍历
System.out.println("\n--- 4.2 Stream.filter + forEach ---");
fruits.stream()
.filter(fruit -> fruit.startsWith("A")) // 筛选出以 "A" 开头的水果
.forEach(fruit -> System.out.println("以 A 开头的水果: " + fruit));
// 输出:
// 水果: Apple
// 水果: Banana
// 水果: Cherry
// 水果: Date
//
// 以 A 开头的水果: Apple
适用场景:
- 当你需要对集合元素进行复杂的转换、过滤、聚合等操作时。
- 当你希望代码更具可读性和声明性时。
- 当你需要利用并行处理来提升性能时。
Java 8+ forEach 和方法引用
这是 Stream API 的一个简化写法,当你的操作非常简单时(比如只是打印),可以使用方法引用让代码更简洁。
// fruits 列表: ["Apple", "Banana", "Cherry", "Date"]
System.out.println("\n--- 5. forEach 和方法引用 ---");
fruits.forEach(System.out::println);
// 输出:
// Apple
// Banana
// Cherry
// Date
适用场景:
- 当你对每个元素执行的操作非常简单,且该操作恰好是某个已存在方法时(如
System.out.println)。 - 代码极度简洁,可读性极高。
总结与最佳实践
| 方法 | 语法 | 是否可修改集合 | 获取索引 | 可读性 | 主要适用场景 |
|---|---|---|---|---|---|
| 传统 For 循环 | for (int i=0; i<list.size(); i++) |
是 (需谨慎) | 是 | 一般 | 需要索引;遍历数组 |
| 增强 For 循环 | for (T item : list) |
否 | 否 | 高 | 最常用,仅需元素 |
| 迭代器 | while (it.hasNext()) |
是 (安全) | 否 | 中等 | 遍历中需修改集合 |
| Stream API | list.stream().forEach(...) |
否 | 否 | 高 (复杂操作时) | 函数式操作、过滤、转换、并行 |
| 方法引用 | list.forEach(System.out::println) |
否 | 否 | 极高 | 简单的、无副作用的操作 |
如何选择?
-
只需要遍历元素,不需要索引,也不需要修改集合:
- 首选
增强 for 循环,它简单、直观、高效。 - 如果操作非常简单(如打印),可以考虑
forEach + 方法引用。
- 首选
-
需要在遍历过程中修改集合(如删除元素):
- 必须使用
迭代器,这是唯一安全的方式。
- 必须使用
-
需要对集合进行复杂的操作(如过滤、转换、聚合、排序):
- 首选
Stream API,它能让你的代码更清晰、更强大,并易于并行化。
- 首选
-
需要获取元素的索引:
- 使用
传统 For 循环,虽然 Java 8 的IntStream也可以实现,但传统循环在这种情况下更直接。
- 使用
现代 Java 开发建议:
- 优先使用 增强 for 循环 和 Stream API。
- 避免在增强 for 循环中直接调用
list.remove()。 - 将
迭代器专门用于需要修改集合结构的场景。
