遍历 List (列表)
假设我们有以下一个 List:

(图片来源网络,侵删)
import java.util.Arrays;
import java.util.List;
public class ListIterationExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry", "Date");
}
}
方法 1:经典 For 循环 (索引遍历)
这是最传统、最基础的方式,通过索引来访问每个元素。
优点:
- 可以获取元素的索引,方便在循环中进行修改或删除(需注意
ConcurrentModificationException)。 - 在 Java 8 之前是唯一的高效遍历方式。
缺点:
- 代码略显冗长。
- 对于
LinkedList等非随机访问列表,通过索引获取元素的性能较差(get(i)是 O(n) 操作)。
代码示例:
System.out.println("--- 1. For 循环 (索引遍历) ---");
for (int i = 0; i < fruits.size(); i++) {
String fruit = fruits.get(i);
System.out.println("索引 " + i + ": " + fruit);
}
方法 2:增强 For 循环 (For-Each 循环)
Java 5 引入的语法糖,是遍历集合和数组最推荐、最简洁的方式。
优点:
- 代码简洁易读。
- 底层使用迭代器,适用于所有
List实现(包括LinkedList),性能稳定。 - 自动处理了迭代器的
hasNext()和next(),不易出错。
缺点:
- 无法获取元素的索引。
- 如果在遍历过程中需要修改集合(非当前元素),可能会抛出
ConcurrentModificationException。
代码示例:
System.out.println("\n--- 2. 增强 For 循环 (For-Each) ---");
for (String fruit : fruits) {
System.out.println("水果: " + fruit);
}
方法 3:使用迭代器 (Iterator)
迭代器是集合框架的一部分,提供了标准的遍历接口。
优点:
- 最安全的遍历方式,特别是在遍历过程中需要删除元素时。
iterator.remove()方法可以在不引发ConcurrentModificationException的情况下安全地删除当前元素。
缺点:
- 代码比 For-Each 循环稍显繁琐。
代码示例:
System.out.println("\n--- 3. 使用迭代器 (Iterator) ---");
// 遍历
for (Iterator<String> iterator = fruits.iterator(); iterator.hasNext(); ) {
String fruit = iterator.next();
System.out.println("水果: " + fruit);
}
// 安全删除元素
// List<String> fruitsToRemove = new ArrayList<>(Arrays.asList("Banana"));
// for (Iterator<String> iterator = fruits.iterator(); iterator.hasNext(); ) {
// String fruit = iterator.next();
// if (fruitsToRemove.contains(fruit)) {
// iterator.remove(); // 安全删除
// }
// }
// System.out.println("删除后的列表: " + fruits);
方法 4:Java 8+ Stream API (流式处理)
Java 8 引入的 Stream API,功能强大,不仅可以遍历,还能进行复杂的链式操作(如过滤、映射、聚合等)。
优点:
- 代码非常简洁,特别是与 Lambda 表达式结合时。
- 支持并行处理,易于利用多核 CPU。
- 将数据操作与数据源(集合)分离,代码更具声明性。
缺点:
- 对于简单的遍历,可能比 For-Each 循环有轻微的性能开销(通常可以忽略不计)。
- 需要学习 Lambda 表达式和 Stream API 的概念。
代码示例:
System.out.println("\n--- 4. Java 8+ Stream API ---");
// 1. 简单遍历
fruits.stream().forEach(fruit -> System.out.println("水果: " + fruit));
// 2. 带过滤的遍历
System.out.println("\n--- 带过滤的遍历 (长度大于5) ---");
fruits.stream()
.filter(fruit -> fruit.length() > 5) // 过滤条件
.forEach(fruit -> System.out.println("长水果名: " + fruit));
遍历 Map (映射)
假设我们有以下一个 Map:
import java.util.HashMap;
import java.util.Map;
public class MapIterationExample {
public static void main(String[] args) {
Map<String, Integer> fruitPrices = new HashMap<>();
fruitPrices.put("Apple", 10);
fruitPrices.put("Banana", 5);
fruitPrices.put("Cherry", 20);
}
}
方法 1:使用 keySet() 和 For-Each 循环
这是最经典、最常用的方式,先获取所有键的集合,然后遍历键,通过键来获取值。
优点:
- 逻辑清晰,易于理解。
- 如果只需要键,或者只需要值,这种方式很灵活。
代码示例:
System.out.println("--- 1. 使用 keySet() 和 For-Each 循环 ---");
// 遍历键
for (String fruit : fruitPrices.keySet()) {
System.out.println("水果: " + fruit);
}
// 遍历键值对
for (String fruit : fruitPrices.keySet()) {
Integer price = fruitPrices.get(fruit);
System.out.println(fruit + " 的价格是: " + price);
}
方法 2:使用 entrySet() 和 For-Each 循环 (推荐)
这是性能最好、最推荐的方式。entrySet() 返回一个 Set<Map.Entry<K, V>>,其中每个 Map.Entry 对象都包含一个键和对应的值。
优点:
- 性能最高:通过
entrySet遍历,只需要一次Map.Entry的查找,而keySet方式需要两次查找(一次找keySet,一次用key找value)。 - 代码更简洁,直接操作键值对。
缺点:
- 如果只需要键或只需要值,它不如
keySet或values()那样直接。
代码示例:
System.out.println("\n--- 2. 使用 entrySet() 和 For-Each 循环 (推荐) ---");
for (Map.Entry<String, Integer> entry : fruitPrices.entrySet()) {
String fruit = entry.getKey();
Integer price = entry.getValue();
System.out.println(fruit + " 的价格是: " + price);
}
方法 3:使用 forEach 方法 (Java 8+)
Java 8 为 Map 接口添加了 forEach 方法,接受一个 BiConsumer(二元消费者)函数,使得遍历代码非常简洁。
优点:
- 代码极其简洁,一行搞定。
- 内部实现通常是基于
entrySet,性能同样很高。
缺点:
- 需要理解 Lambda 表达式。
代码示例:
System.out.println("\n--- 3. 使用 Map.forEach() (Java 8+) ---");
fruitPrices.forEach((fruit, price) -> System.out.println(fruit + " 的价格是: " + price));
方法 4:使用迭代器 (Iterator)
与 List 类似,也可以使用迭代器来遍历 keySet 或 entrySet,这在需要安全删除元素时很有用。
代码示例:
System.out.println("\n--- 4. 使用迭代器 (Iterator) ---");
Iterator<Map.Entry<String, Integer>> iterator = fruitPrices.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
// 示例:删除价格小于10的水果
if (entry.getValue() < 10) {
iterator.remove(); // 安全删除
}
}
System.out.println("删除后的 Map: " + fruitPrices);
总结与推荐
| 数据结构 | 推荐方式 | 理由 |
|---|---|---|
| List | 增强 For 循环 (For-Each) | 代码简洁、易读、性能稳定,适用于 99% 的场景。 |
| Java 8+ Stream API | 当需要进行复杂的链式操作(如 filter, map, reduce)时使用。 |
|
| Map | entrySet() + For-Each |
性能最高,代码清晰,是遍历 Map 的黄金标准。 |
Map.forEach() (Java 8+) |
代码最简洁,一行搞定,性能与 entrySet 相当,是现代 Java 的首选。 |
核心建议:
- 遍历 List:优先使用 For-Each 循环。
- 遍历 Map:优先使用
entrySet()+ For-Each 或Map.forEach()。 - 如果只是简单地打印或处理每个元素,For-Each 和
forEach是最佳选择。 - 如果在遍历过程中需要删除元素,请务必使用 迭代器 的
remove()方法,或者使用 Java 8+ 的removeIf方法。 - 如果需要对数据进行转换、过滤、聚合等复杂操作,请使用 Stream API。
