当前教程
转换简单循环
系列中的下一个

系列中的下一个: 转换带步长的循环

转换简单循环

此页面由 Venkat SubramaniamUPL 下贡献

 

命令式与函数式风格

较早版本的 Java 支持面向对象范式与命令式编程风格的混合。从 Java 8 开始,您也可以在代码中混合使用函数式编程风格。如果您的代码库是在 Java 7 或更早版本期间开始的,或者后来由主要熟悉较早版本 Java 的程序员编写,它将充满了命令式风格的代码。

命令式风格是指我们告诉做什么以及如何做。函数式风格本质上是声明式的,我们告诉做什么,并将如何做或细节委托给底层库。命令式风格的代码可能更容易编写,因为我们大多数人都非常熟悉它。但是,代码变得冗长、复杂且难以阅读。函数式风格可能一开始很难,主要是因为大多数程序员不太熟悉它。总的来说,它更容易阅读、理解和更改。随着练习,编写起来也会变得更容易。

在这个 教程系列 中,我们将研究一些常见的命令式风格代码,并找到一个映射或等效的函数式风格代码,我们可以用它来代替。当您使用基于代码的代码时,当您准备好修复错误或进行增强时,您可能会发现将一些命令式风格的代码重构为函数式风格很有用。您可以使用本教程作为指南,为一些常见情况找到命令式到函数式风格的映射。

在本教程中,我们将重点关注简单的循环。

 

简单的 for 循环

让我们从传统的 for 循环开始,我们在其中对一个范围内索引的值执行操作。

for(int i = 0; i < 5; i++) {
  System.out.println(i);
}

在上面的代码中,本质是范围,从 0 到小于 5 的一个值。仪式,噪音,来自 如何,是语法加上索引变量 i 上的增量操作。我们可以保留本质并通过将代码转换为函数式风格来消除仪式。

如果您想使用函数式风格来编写此 for 循环,您可以非常轻松地做到,提示就在代码之前的句子中:索引在一个范围内。由于我们正在遍历一个范围,因此 IntStreamrange 方法是对此的直接等效项。

import java.util.stream.IntStream;

...
IntStream.range(0, 5)
  .forEach(i -> System.out.println(i));

您可以通过对 println 方法使用方法引用来进一步使代码简洁。

import java.util.stream.IntStream;

...
IntStream.range(0, 5)
  .forEach(System.out::println);

函数式风格的代码更简洁、更容易阅读,并且与命令式版本相比,此版本的意图更清晰。

如果您的 for 循环运行到包含结束值,就像在以下代码中一样,您可能会想知道。

for(int i = 0; i <= 5; i++) {
  System.out.println(i);
}

IntStream 接口为您提供了覆盖,它有一个 rangeClosed 方法专门用于此目的。

import java.util.stream.IntStream;

...
IntStream.rangeClosed(0, 5)
  .forEach(System.out::println);

rangeClosed 方法对于从起始值迭代到包含结束值非常有用。

无论您使用 range 方法还是 rangeClosed 方法,您都会获得一个 int 值流,您可以使用内部迭代器在其上执行操作。在本系列的后面,我们将研究超越 forEach 的操作。

在前面的代码示例中,内部迭代器消除了您肩上的迭代负担。流负责一次遍历一个值范围。您只需要专注于对每个元素做什么,因为它们是在 forEach 方法中提供给您的。在我们的示例中,我们只是打印了提供的值。您可以执行任何您喜欢的操作,例如将信息保存到数据库、将其发送到远程服务等。

for 循环提供的外部迭代器不同,使用内部迭代器的代码更简洁、噪音更少、避免了显式修改索引变量的需要、更容易阅读、更容易修改,并且更令人愉快地使用。

继续在您自己的代码库中寻找机会,您会在其中看到传统的 for 循环,并将其修改为使用 IntStreamrangerangeClosed 方法。确保在更改后验证代码按预期工作,最好通过运行您可能已经拥有的自动化测试。

 

映射

在您看到简单的 for 循环的任何地方,您都可以使用 IntStreamrangerangeClosed 方法。如果您想迭代到但不包括结束值,请使用 range 方法。使用 rangeClosed 也将结束值包含在您的迭代中。


上次更新: 2023 年 7 月 6 日


当前教程
转换简单循环
系列中的下一个

系列中的下一个: 转换带步长的循环