系列中的上一篇
当前教程
将 foreach 与 if 转换
系列中的下一篇

系列中的上一篇: 转换带步长的循环

系列中的下一篇: 转换带转换的迭代

将 foreach 与 if 转换

此页面由 Venkat SubramaniamUPL 下贡献

 

使用 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);
  }
}

对于函数式风格,Streamfilter 方法直接替换了命令式风格的 iffilter 方法将允许集合中的元素通过函数管道中的下一阶段,如果传递给 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 日


系列中的上一篇
当前教程
将 foreach 与 if 转换
系列中的下一篇

系列中的上一篇: 转换带步长的循环

系列中的下一篇: 转换带转换的迭代