1. 概述

多年来,空引用(null references)和值一直在困扰着程序员。null引用的发明者Tony Hoare甚至称其为“十亿美元的错误”。特别是Java,一直在与null值及其令人畏惧的NullPointerException进行斗争。

Java 8引入了Optional类来应对这个挑战,确保妥善处理null和空结果。在这篇教程中,我们将探讨如何在所有Optional变量都包含值时执行操作,否则忽略该操作。

2. 假设

本教程演示了使用三个Optional变量,但概念可以轻松扩展以处理更多。此外,让我们声明这些变量,这些将在本文中使用:

var name = Optional.of("Jean-Luc Picard");
var designation = Optional.of("Captain");
var ship = Optional.of("USS Enterprise D");

在这个例子中,为了简洁,我们定义了Optional<String>。然而,文章中讨论的原则同样适用于其他引用类型。

3. 使用isPresent()

Optional提供了一个有用的isPresent()方法,用于检查其中是否包含值。如果存在值,此方法返回true,如果Optional为空,则返回false。让我们看看实现:

var action = false;
if (name.isPresent() && designation.isPresent() && ship.isPresent()) {
    action = true;
}
Assertions.assertTrue(action);

在这个示例中,我们使用Optional.of()创建Optional实例。然后,我们在每个实例上使用isPresent(),并在所有值都存在时才执行操作。虽然这种方法明显简单且易于阅读,但在处理多个变量时会变得繁琐。

4. 使用flatMap()map()

Java 8将函数式编程概念引入了语言。通过flatMap()map()等方法,我们现在可以在容器类型(如Optional)中的值上执行操作。利用flatMap()map(),我们可以有效地只在所有值都存在时检查并执行操作。

让我们看看使用这种方法的实现:

var action = name.flatMap(n -> designation.flatMap(d -> ship.map(s -> true)));
Assertions.assertEquals(action, Optional.of(true));

在上述示例中,我们使用flatMap()map()链接多个Optional实例。这些函数设计为短路操作;如果链中的任何步骤没有值,操作立即终止,并返回一个空的结果

我们可以通过引入另一个测试用例来验证这种行为:

var name = Optional.of("Jean-Luc Picard");
var designation = Optional.of("Captain");
var ship = Optional.empty();
var action = name.flatMap(n -> designation.flatMap(d -> ship.map(s -> true)));
Assertions.assertTrue(action.isEmpty());

在这里,我们可以看到action变量是空的,因为船只没有值。

虽然这种方法强大,但当需要连接众多值时,它往往会变得更加冗长。

5. 使用ifPresent()

另一种选择是,如果我们不需要返回值,只需要在所有值都存在时执行操作,我们可以使用ifPresent()配合lambda表达式。让我们看看示例代码:

name.ifPresent(n -> designation.ifPresent(d -> ship.ifPresent(s -> System.out.println("Perform action instead!"))));

在这种情况下,我们使用ifPresent()链接每个Optional实例,并仅在所有值都存在时执行操作。

6. 使用Stream.of()

Java流提供了另一种确保只有在所有值都存在时才执行操作的方法。我们可以使用Stream.of()创建一个Optional值的流,并使用allMatch()方法检查流中的每个元素是否包含值。

让我们看看实现:

var status = false;
var allPresent = Stream.of(name, designation, ship).allMatch(Optional::isPresent);
if (allPresent) {
    // Perform action if all values present
    status = true;
}
Assertions.assertTrue(status);

在这个示例中,我们使用allMatch()Optional.isPresent()一起验证流中的所有元素都存在。

这提供了一种简洁的方式来执行所需的验证。与其他方法不同,添加更多的Optional值并不会降低可读性。这使得流成为处理越来越多Optional值的高可扩展解决方案。

7. 总结

在这篇教程中,我们探讨了在所有Optional值都可用时执行操作的不同方法。我们首先检查了简单的if...else条件,然后探索了利用函数式编程概念和流API的替代技术。最终,最合适的实现方式取决于具体情境的需求。

如往常一样,本文使用的示例代码可在GitHub上找到。


« 上一篇: Convert a Queue to a List
» 下一篇: SSHJ简介