可选类型是在 Java 8 中引入的,用于帮助开发人员正确处理可空值。
Java 9 在 Optional API 中引入了一些额外的方法,以进一步增强其功能。
在本文中,我将带您了解 Java 9 中引入的这些新方法,并提供简单的示例来演示它们的用法。
如果您不熟悉 Optional 并且想先阅读基础知识,请查看我的 Java 8 Optional 教程。
在本文中,我将使用 JShell 来运行所有代码示例。 JShell 也是 Java 9 的一个新特性。您可以从我的 Java 9 JShell 简介中了解更多信息。
好的!现在让我们一一看看 Optional API 中添加的所有新方法。
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 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。
新的 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-Optionals 到 Stream-of-Values 转换将自动过滤掉非空的 Optional 元素。
Optional API 中的这些新改进肯定会帮助 Java 开发人员使用 Optionals 编写更好的代码。
我真的很喜欢添加 ifPresentOrElse()
方法。我几乎每次都遇到需要在我的代码中编写 If-Present-Else 逻辑的情况,我不得不用 isPresent()
编写 if-else
代码。但是现在我可以使用这个新方法为这两种情况传递两个 lambda 表达式。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.callicoder.com/java-9-optional-api-enhancements/
内容来源于网络,如有侵权,请联系作者删除!