Java中for each循环的工作原理详解

Java中for each循环的工作原理详解

技术背景

在Java编程中,循环是一种常见的控制结构,用于重复执行一段代码。传统的for循环和while循环在很多场景下都能很好地完成任务,但在遍历集合或数组时,代码可能会显得冗长且容易出错。为了简化这种操作,Java 5引入了for each循环(也称为增强型for循环),它提供了一种更简洁、更易读的方式来遍历集合和数组。

实现步骤

1. 遍历集合

当使用for each循环遍历实现了Iterable接口的集合时,它会使用集合的迭代器来依次访问集合中的每个元素。以下是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.ArrayList;
import java.util.List;

public class ForEachCollectionExample {
public static void main(String[] args) {
List<String> someList = new ArrayList<>();
someList.add("monkey");
someList.add("donkey");
someList.add("skeleton key");

// 使用for each循环遍历集合
for (String item : someList) {
System.out.println(item);
}
}
}

上述代码中,for each循环会自动获取someList的迭代器,并依次调用hasNext()next()方法来访问集合中的元素。

2. 遍历数组

当使用for each循环遍历数组时,它会使用数组的索引来依次访问数组中的每个元素。以下是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
public class ForEachArrayExample {
public static void main(String[] args) {
String[] fruits = {"Orange", "Apple", "Pear", "Strawberry"};

// 使用for each循环遍历数组
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}

上述代码中,for each循环会自动使用数组的索引从0开始,依次访问数组中的元素,直到遍历完整个数组。

核心代码

1. 集合遍历的等价代码

如果不使用for each语法,遍历集合的等价代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ForEachCollectionEquivalent {
public static void main(String[] args) {
List<String> someList = new ArrayList<>();
someList.add("monkey");
someList.add("donkey");
someList.add("skeleton key");

// 不使用for each循环,使用迭代器遍历集合
for (Iterator<String> i = someList.iterator(); i.hasNext(); ) {
String item = i.next();
System.out.println(item);
}
}
}

2. 数组遍历的等价代码

如果不使用for each语法,遍历数组的等价代码如下:

1
2
3
4
5
6
7
8
9
10
11
public class ForEachArrayEquivalent {
public static void main(String[] args) {
String[] fruits = {"Orange", "Apple", "Pear", "Strawberry"};

// 不使用for each循环,使用普通for循环遍历数组
for (int i = 0; i < fruits.length; i++) {
String fruit = fruits[i];
System.out.println(fruit);
}
}
}

最佳实践

1. 选择合适的循环方式

  • 当只需要顺序访问集合或数组中的每个元素,而不需要访问索引时,建议使用for each循环,因为它更简洁、易读。
  • 当需要在遍历过程中访问索引,或者需要对集合进行修改(如删除元素)时,建议使用传统的for循环或迭代器。

2. 性能考虑

  • 对于数组,使用传统的for循环通过索引访问元素通常比for each循环更快,因为for each循环需要额外的迭代器开销。
  • 对于集合,使用for each循环通常比传统的for循环通过索引访问元素更快,因为集合的迭代器可以更高效地遍历元素。

常见问题

1. 无法修改集合元素

for each循环中,不能直接修改集合中的元素。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.ArrayList;
import java.util.List;

public class ForEachModifyExample {
public static void main(String[] args) {
List<String> someList = new ArrayList<>();
someList.add("monkey");
someList.add("donkey");
someList.add("skeleton key");

// 尝试在for each循环中修改集合元素
for (String item : someList) {
item = "new value"; // 这不会修改集合中的元素
}

// 输出集合元素,发现元素未被修改
for (String item : someList) {
System.out.println(item);
}
}
}

上述代码中,尝试在for each循环中修改集合元素,但实际上并没有修改集合中的元素。如果需要修改集合元素,建议使用传统的for循环或迭代器。

2. 并发修改异常

for each循环中,如果尝试修改集合的结构(如添加或删除元素),会抛出ConcurrentModificationException异常。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.ArrayList;
import java.util.List;

public class ForEachConcurrentModificationExample {
public static void main(String[] args) {
List<String> someList = new ArrayList<>();
someList.add("monkey");
someList.add("donkey");
someList.add("skeleton key");

// 尝试在for each循环中删除集合元素
try {
for (String item : someList) {
if (item.equals("donkey")) {
someList.remove(item); // 会抛出ConcurrentModificationException异常
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

上述代码中,尝试在for each循环中删除集合元素,会抛出ConcurrentModificationException异常。如果需要修改集合结构,建议使用迭代器的remove()方法。


Java中for each循环的工作原理详解
https://119291.xyz/posts/2025-04-27.java-for-each-loop-working-principle/
作者
ww
发布于
2025年4月27日
许可协议