Java 9 Optional API增强功能介绍

x33g5p2x  于2021-10-17 转载在 Java  
字(3.6k)|赞(0)|评价(0)|浏览(344)

可选类型是在 Java 8 中引入的,用于帮助开发人员正确处理可空值。

Java 9 在 Optional API 中引入了一些额外的方法,以进一步增强其功能。

在本文中,我将带您了解 Java 9 中引入的这些新方法,并提供简单的示例来演示它们的用法。

如果您不熟悉 Optional 并且想先阅读基础知识,请查看我的 Java 8 Optional 教程。

在本文中,我将使用 JShell 来运行所有代码示例。 JShell 也是 Java 9 的一个新特性。您可以从我的 Java 9 JShell 简介中了解更多信息。

好的!现在让我们一一看看 Optional API 中添加的所有新方法。

Java 9 Optional.or() 方法

Optional 已经有两个方法,即 orElse()orElseGet() 来在 Optional 为空时返回默认值。

例如,考虑以下空的 Optional -

jshell> Optional<String> greeting = Optional.empty()
greeting ==> Optional.empty

您可以使用 orElse() 方法与上述 Optional 直接返回这样的默认值 -

jshell> String greetingText = greeting.orElse("Hello, World");
greetingText ==> "Hello, World"

或者,您可以使用 orElseGet() 方法提供一个 Supplier 函数,该函数返回默认值 -

jshell> String greetingText = greeting.orElseGet(() -> {
   ...>     Random rand = new Random();
   ...>     return "Hello CalliCoder Blog Readers - " + rand.nextInt(10);
   ...> })
greetingText ==> "Hello CalliCoder Blog Readers - 7"

当 Optional 为空时,这两种方法都返回一个默认值。如果 Optional 不为空,这些方法将返回 Optional 中的值而不是默认值。在任何情况下,最终返回的值都是未包装的类型而不是 Optional。

但是,在某些情况下,您可能希望最终返回的值是 Optional 而不是简单类型。

or() 方法是为这些情况提供的。它类似于 orElseGet() 方法,除了它采用的供应商函数,返回一个 Optional 而不是简单类型 -

jshell> Optional<String> optionalGreetingText = greeting.or(() -> {
   ...>     String text = "Nullable Greeting";
   ...>     return Optional.ofNullable(text);
   ...> });
optionalGreetingText ==> Optional[Nullable Greeting]

如您所见,在这种情况下,最终结果是 Optional 而不是简单类型。如果存在值,or() 方法返回原始 Optional,否则返回由供应商函数生成的 Optional。

Java 9 Optional.ifPresentOrElse() 方法

您将如何使用 Java 8 Optional 编写 If-Present-Else 逻辑?

您可以使用 isPresent() 方法来检查值是否存在,并执行以下操作 -

jshell> Optional<String> name = Optional.ofNullable("Rajeev");
name ==> Optional[Rajeev]

jshell> if(name.isPresent()) {
   ...>     System.out.println("Hello " + name.get());
   ...> } else {
   ...>     System.out.println("Hello Guest");
   ...> }
Hello Rajeev

这很好,但太冗长了。我们还有一个 ifPresent() 方法,它接受一个 Consumer 函数,该函数在 Optional 中存在值时调用 -

jshell> name.ifPresent(value -> System.out.println("Hello " + value));
Hello Rajeev

ifPresent() 方法方便且不那么冗长,因为我们可以以 lambda 表达式的形式传递 Consumer 函数。但不幸的是,当我们使用 ifPresent() 时,我们无法编写 Else 逻辑。

这正是 ifPresentOrElse() 方法的用途 -

jshell> name.ifPresentOrElse(
   ...>     value -> System.out.println("Hello " + value),
   ...>     () -> System.out.println("Hello Guest")
   ...> )
Hello Rajeev

ifPresentOrElse() 方法接受两个参数 - Consumer 和 Runnable。我们可以将两者作为 lambda 表达式传递给方法。

如果 Optional 中存在值,则调用 Consumer,如果 Optional 为空,则调用 Runnable。

Java 9 Optional.stream() 方法

新的 stream() 方法允许您将 Optional 转换为 Stream

如果 Optional 包含一个值,它将返回一个只包含该值的 Stream,否则,它将返回一个空 Stream -

jshell> Optional<String> myOptional = Optional.of("foo")
myOptional ==> Optional[foo]

jshell> Stream<String> myOptionalStream = myOptional.stream()
myOptionalStream ==> java.util.stream.ReferencePipeline$Head@65e2dbf3

jshell> myOptionalStream.forEach(System.out::println)
foo

stream() 方法在处理一组 Optional 元素时非常有用。它将自动过滤掉非空的 Optionals 并允许您无缝地在 Optionals 上编写转换。

以下是使用 Java 9 的 stream() 方法将可选元素列表转换为值流的方法-

jshell> List<Optional<String>> animalOptionals = List.of(Optional.of("Elephant"), Optional.empty(), Optional.of("Lion"), Optional.of("Tiger"), Optional.empty())
animalOptionals ==> [Optional[Elephant], Optional.empty, Optional[Lio ... al[Tiger], Optional.empty]

jshell> Stream<String> animals = animalOptionals.stream().flatMap(Optional::stream)
animals ==> java.util.stream.ReferencePipeline$7@551aa95a

jshell> animals.forEach(System.out::println)
Elephant
Lion
Tiger

由于 Optional.stream() 方法在 Optional 为空时返回一个空流,因此上面的 List-of-OptionalsStream-of-Values 转换将自动过滤掉非空的 Optional 元素。

结论

Optional API 中的这些新改进肯定会帮助 Java 开发人员使用 Optionals 编写更好的代码。

我真的很喜欢添加 ifPresentOrElse() 方法。我几乎每次都遇到需要在我的代码中编写 If-Present-Else 逻辑的情况,我不得不用 isPresent() 编写 if-else 代码。但是现在我可以使用这个新方法为这两种情况传递两个 lambda 表达式。

相关文章

微信公众号

最新文章

更多