假设我们有以下 ArrayList 作为示例:

import java.util.ArrayList;
import java.util.List;
public class ArrayListTraversal {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add("Mango");
}
}
经典 for 循环 (索引遍历)
这是最传统、最基础的遍历方式,通过索引来访问每一个元素。
代码示例:
System.out.println("--- 方法一:经典 for 循环 ---");
for (int i = 0; i < fruits.size(); i++) {
String fruit = fruits.get(i);
System.out.println(fruit);
}
优点:
- 直观易懂:对于初学者来说非常容易理解。
- 随机访问:如果循环体内需要根据索引进行其他操作(获取前一个或后一个元素),这种方式非常方便。
- 兼容性好:适用于所有版本的 Java。
缺点:

- 代码冗余:需要手动管理索引变量
i。 - 性能问题:对于
LinkedListget(i)方法性能很差(需要从头遍历),虽然ArrayList的get(i)是 O(1) 时间复杂度,但这种方式本身不具备通用性。
增强 for 循环 (For-Each 循环)
这是 Java 5 引入的特性,专门用于遍历集合和数组,语法简洁,是目前最推荐的遍历方式。
代码示例:
System.out.println("\n--- 方法二:增强 for 循环 (For-Each) ---");
for (String fruit : fruits) {
System.out.println(fruit);
}
优点:
- 代码简洁:语法非常优雅,可读性高。
- 不易出错:无需关心索引的边界条件,避免了
ArrayIndexOutOfBoundsException。 - 性能优秀:对于
ArrayList,其内部实现和经典 for 循环性能几乎完全相同。
缺点:

- 无法获取索引:如果循环体内需要知道当前元素的索引,此方法不适用。
- 无法修改集合本身:不能在遍历过程中安全地使用
remove()方法删除元素(会抛出ConcurrentModificationException),如果需要删除元素,请使用方法三或方法四。
迭代器 (Iterator)
迭代器是专门为集合遍历而设计的接口,它提供了一种“安全”的方式来遍历和修改集合。
代码示例:
System.out.println("\n--- 方法三:迭代器 ---");
// 获取迭代器
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
// 示例:安全地删除元素
// if ("Orange".equals(fruit)) {
// iterator.remove(); // 使用迭代器的 remove() 方法是安全的
// }
}
重要提示:
remove()的正确用法:如果你想遍历时删除元素,必须调用iterator.remove(),而不是list.remove()。list.remove()会快速失败,抛出ConcurrentModificationException。
优点:
- 最安全:是唯一可以在遍历过程中安全地删除元素的官方方式。
- 通用性强:适用于所有实现了
Collection接口的集合(包括LinkedList,HashSet等),无论它们是否支持随机访问。 - 解耦:将遍历逻辑与集合的底层实现分离开来。
缺点:
- 代码稍显冗长:相比 For-Each 循环,代码量稍多。
Java 8+ Stream API
这是 Java 8 引入的函数式编程特性,功能非常强大,不仅可以遍历,还可以进行过滤、映射、聚合等各种复杂操作。
代码示例:
System.out.println("\n--- 方法四:Stream API ---");
// 1. 简单遍历
fruits.stream().forEach(fruit -> System.out.println(fruit));
// 2. 结合过滤和遍历(只打印长度大于 5 的水果)
System.out.println("\n--- Stream API 结合过滤 ---");
fruits.stream()
.filter(fruit -> fruit.length() > 5) // 过滤条件
.forEach(fruit -> System.out.println(fruit)); // 对过滤后的元素执行操作
优点:
- 功能强大:非常适合进行链式调用,实现复杂的集合处理逻辑。
- 代码简洁(复杂场景下):当需要处理和转换数据时,一行代码可以完成传统多行代码的工作。
- 并行处理:只需将
stream()换成parallelStream(),即可轻松实现并行处理,提升大数据量下的性能。
缺点:
- 开销稍大:对于简单的遍历,相比传统方式会有微小的性能开销。
- 学习曲线:对于不熟悉函数式编程的开发者来说,需要一定的学习成本。
总结与选择建议
| 方法 | 代码示例 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 经典 for 循环 | for (int i=0; i<list.size(); i++) |
直观,可获取索引 | 代码冗余,通用性差 | 需要使用索引进行操作时 |
| 增强 for 循环 | for (T item : list) |
简洁,易读,性能好 | 无法获取索引,不能安全删除 | 日常遍历的首选,绝大多数遍历场景 |
| 迭代器 | while (iterator.hasNext()) |
可安全删除,通用性强 | 代码稍长 | 需要在遍历过程中添加或删除元素时 |
| Stream API | list.stream().forEach(...) |
功能强大,可并行,易链式调用 | 有开销,学习成本高 | 需要进行复杂的数据处理、过滤、转换时 |
-
只是想简单地、从头到尾地打印或处理每个元素?
- 使用增强 for 循环 (For-Each),这是最简单、最直接、最高效的选择。
-
需要在遍历的时候删除某些元素?
- 使用迭代器,并调用
iterator.remove()。
- 使用迭代器,并调用
-
需要对集合进行更复杂的操作,比如筛选、转换、排序、统计等?
- 使用 Stream API,这是现代 Java 开发的趋势。
-
在循环中需要用到元素的索引?
- 使用经典 for 循环。
