将 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 日