将 foreach 与 if 转换
此页面由 Venkat Subramaniam 在 UPL 下贡献使用 foreach 迭代
在本 教程系列 的前几篇文章中,我们介绍了如何将用命令式风格编写的循环转换为函数式风格。在本文中,我们将了解如何将使用 foreach 的命令式风格迭代转换为函数式风格。此外,我们还将了解如何使用 if 转换将选定的元素提取到函数式风格中。
Java 5 引入了非常流行的 foreach 语法。例如,要遍历表示名称的 String 集合,我们可以编写类似 for(String name: names) 的代码。在底层,foreach 在字节码级别被转换为使用 Iterator——当迭代器告诉我们还有另一个元素时,获取下一个元素进行处理。换句话说,foreach 是使用 while 循环遍历 Iterator 提供的元素的迭代的简洁语法糖。我们可以很容易地将 foreach 转换为函数式风格。让我们看看如何操作。
从命令式到函数式风格
以下是用 foreach 遍历名称集合的迭代示例
List<String> names = List.of("Jack", "Paula", "Kate", "Peter");
for(String name: names) {
System.out.println(name);
}
在每次迭代中,name 变量都会绑定到一个新值,因为迭代从给定集合中的一个元素推进到下一个元素。将命令式风格的 foreach 转换为函数式风格是直接使用 forEach 内部迭代器方法。它被称为内部迭代器,因为推进到下一个元素是在内部自动处理的,而不是在外部或显式处理。
让我们重构循环以使用函数式风格。
List<String> names = List.of("Jack", "Paula", "Kate", "Peter");
names.forEach(name -> System.out.println(name));
这非常简单,for 循环变成了对集合上的 forEach() 方法的调用。在每次迭代中,作为参数传递给 forEach() 的 lambda 会使用集合中的下一个元素调用。
接下来显示了使用 stream() 的这种迭代的略微变化。
List<String> names = List.of("Jack", "Paula", "Kate", "Peter");
names.stream()
.forEach(name -> System.out.println(name));
forEach() 方法在 Collection<T> 和 Stream<T> 上都可用。像 filter() 这样的函数(我们很快就会使用)仅在 Stream<T> 上可用,而不在 Collection 上可用。这是为了在多个中间操作可能先于像 forEach()、findFirst() 等终端操作时提供效率。
使用 if 选择元素
假设在迭代过程中,我们想根据某个条件从集合中选择一些值。例如,如果我们只想打印长度为 4 的名称怎么办?在命令式风格中,我们可以执行以下操作
List<String> names = List.of("Jack", "Paula", "Kate", "Peter");
for(String name: names) {
if(name.length() == 4) {
System.out.println(name);
}
}
对于函数式风格,Stream 的 filter 方法直接替换了命令式风格的 if。filter 方法将允许集合中的元素通过函数管道中的下一阶段,如果传递给 filter() 方法的谓词(作为 lambda 传递)计算结果为 true;否则,该值将被丢弃,不再进行进一步处理。
让我们将之前的代码转换为函数式风格
List<String> names = List.of("Jack", "Paula", "Kate", "Peter");
names.stream()
.filter(name -> name.length() == 4)
.forEach(name -> System.out.println(name));
filter() 方法就像一个门,它打开让一些元素通过,关闭拒绝或丢弃一些元素,因为迭代在向前推进。
我们在前几篇文章中看到了传统 for 循环的函数式风格等效项。在本文中,我们了解了 Java 5 的命令式风格 foreach 如何转换为函数式风格中的优雅语法。此外,命令式风格循环中的 if 条件转换为对 Stream API 的 filter() 方法的调用。
映射
在任何看到 foreach 循环的地方,直接在集合上使用 forEach() 方法。如果 foreach 的主体包含一个 if 语句来选择一些值,那么使用 stream() API 并调用 filter() 方法。
上次更新: 2023 年 11 月 14 日