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

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);
}
优点
- 直观易懂:对于初学者来说最容易理解。
- 灵活性高:可以在遍历过程中方便地获取元素的索引
i,可以轻松地访问前一个或后一个元素(list.get(i-1))。 - 性能:对于
ArrayList,get(i)操作是 O(1) 时间复杂度,因此整体性能非常好。
缺点
- 代码冗长:需要手动管理索引变量
i,代码看起来比较啰嗦。 - 不适用于所有 List 实现:对于
LinkedList,get(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);
}
优点
- 代码简洁:语法非常简洁,可读性高。
- 安全性高:不会出现数组越界等索引相关的错误。
- 通用性强:适用于所有实现了
Iterable接口的集合(包括ArrayList,LinkedList,HashSet等),性能稳定。
缺点
- 无法获取索引:如果遍历过程中需要知道当前元素的索引,此方法无能为力。
- 无法修改集合本身:在遍历过程中,不能直接添加或删除集合中的元素(会抛出
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);
}
优点
- 安全删除元素:这是
Iterator最核心的优势,在遍历过程中,只能通过iterator.remove()方法来删除刚刚由next()返回的元素,这样可以避免ConcurrentModificationException。 - 通用性强:和 for-each 一样,适用于所有集合。
缺点
- 代码稍显复杂:相比 for-each 循环,代码要多几行。
- 无法获取索引:同样无法直接获取元素的索引。
Java 8+ 中的 forEach 方法
Iterator 也可以结合 Java 8 的 Lambda 表达式使用,使代码更简洁:

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)); // 遍历
优点
- 声明式编程:你只需要“声明”你想做什么(如“过滤”、“排序”),而不需要关心“怎么做”,代码更易读。
- 功能强大:可以轻松进行链式操作,组合多种复杂的处理逻辑。
- 并行处理:只需将
stream()换成parallelStream(),即可轻松实现并行计算,提升大数据集的处理效率。
缺点
- 性能开销:对于简单的遍历,Stream API 会比传统的 for 循环有轻微的性能开销(因为涉及函数调用和流对象创建)。
- 学习曲线:对于初学者,理解函数式概念(如
filter,map,lambda)需要时间。
总结与最佳实践
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 经典 for 循环 | 直观,可获取索引,ArrayList 性能好 |
代码冗长,LinkedList 性能差 |
仅用于 ArrayList,且需要索引时。 |
| 增强 for 循环 (for-each) | 代码简洁,可读性高,安全通用 | 无法获取索引,遍历中不能修改集合 | 绝大多数遍历场景的首选,尤其是只读遍历。 |
| Iterator | 唯一能在遍历中安全删除元素的方式 | 代码稍复杂,无法获取索引 | 需要在遍历过程中删除元素时。 |
| Stream API | 功能强大,声明式,易于并行化 | 简单遍历有开销,学习曲线陡 | 需要进行复杂的数据处理(过滤、映射、聚合等)。 |
如何选择?
-
日常遍历,只读操作:直接使用
for-each循环,这是最常见、最安全、最简洁的选择。for (String fruit : fruits) { // ... } -
遍历
ArrayList且需要索引:可以使用经典 for 循环。for (int i = 0; i < fruits.size(); i++) { String fruit = fruits.get(i); // ... 使用 i } -
需要在遍历中删除元素:必须使用
Iterator。
(图片来源网络,侵删)Iterator<String> iterator = fruits.iterator(); while (iterator.hasNext()) { String fruit = iterator.next(); if (shouldRemove(fruit)) { iterator.remove(); // 安全删除 } } -
需要进行复杂的数据处理(过滤、转换等):使用 Stream API。
List<String> longFruits = fruits.stream() .filter(f -> f.length() > 5) .collect(Collectors.toList());
