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 (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 (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 (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 (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 (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");
try { for (String item : someList) { if (item.equals("donkey")) { someList.remove(item); } } } catch (Exception e) { e.printStackTrace(); } } }
|
上述代码中,尝试在for each
循环中删除集合元素,会抛出ConcurrentModificationException
异常。如果需要修改集合结构,建议使用迭代器的remove()
方法。