Java 9对Optional API的增强

2023/07/03

1. 概述

在本文中,我们将研究Java 9对Optional API的补充。

除了模块化之外,Java 9还为Optional类添加了3个非常有用的方法。

2. or()方法

有时,当我们的Optional为空时,我们想要执行一些其他也返回Optional的操作。

在Java 9之前,Optional类只有orElse()和orElseGet()方法,但两者都需要返回未包装的值。

Java 9引入了or()方法,如果我们的Optional为空,它会延迟返回另一个Optional。如果我们的第一个Optional有一个定义的值,则传递给or()方法的lambda将不会被调用,也不会计算和返回值:

@Test
public void givenOptional_whenPresent_thenShouldTakeAValueFromIt() {
    //given
    String expected = "properValue";
    Optional<String> value = Optional.of(expected);
    Optional<String> defaultValue = Optional.of("default");

    //when
    Optional<String> result = value.or(() -> defaultValue);

    //then
    assertThat(result.get()).isEqualTo(expected);
}

在Optional为空的情况下,返回结果将与defaultValue相同:

@Test
public void givenOptional_whenEmpty_thenShouldTakeAValueFromOr() {
    // given
    String defaultString = "default";
    Optional<String> value = Optional.empty();
    Optional<String> defaultValue = Optional.of(defaultString);

    // when
    Optional<String> result = value.or(() -> defaultValue);

    // then
    assertThat(result.get()).isEqualTo(defaultString);
}

3. ifPresentOrElse()方法

当我们有一个Optional实例时,我们通常希望对它的基础值执行特定的操作。另一方面,如果Optional为空,我们希望记录它或通过增加一些指标来跟踪该事实。

ifPresentOrElse()方法正是为此类场景创建的。我们可以传递一个Consumer,如果定义了Optional将被调用,以及如果Optional为空则将执行Runnable。

假设我们有一个已定义的Optional,如果该值存在,我们想自增一个特定的计数器:

@Test
public void givenOptional_whenPresent_thenShouldExecuteProperCallback() {
    // given
    Optional<String> value = Optional.of("properValue");
    AtomicInteger successCounter = new AtomicInteger(0);
    AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

    // when
    value.ifPresentOrElse(
        v -> successCounter.incrementAndGet(), 
        onEmptyOptionalCounter::incrementAndGet);

    // then
    assertThat(successCounter.get()).isEqualTo(1);
    assertThat(onEmptyOptionalCounter.get()).isEqualTo(0);
}

请注意,作为第二个参数传递的回调未执行。

在Optional为空的情况下,将执行第二个回调:

@Test
public void givenOptional_whenNotPresent_thenShouldExecuteProperCallback() {
    // given
    Optional<String> value = Optional.empty();
    AtomicInteger successCounter = new AtomicInteger(0);
    AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

    // when
    value.ifPresentOrElse(
      v -> successCounter.incrementAndGet(), 
      onEmptyOptionalCounter::incrementAndGet);

    // then
    assertThat(successCounter.get()).isEqualTo(0);
    assertThat(onEmptyOptionalCounter.get()).isEqualTo(1);
}

4. stream()方法

在Java 9中添加到Optional类的最后一个方法是stream()方法。

Java有一个非常流式和优雅的Stream API,可以对集合进行操作并利用许多函数式编程概念。最新的Java版本在Optional类上引入了stream()方法,允许我们将Optional实例视为Stream

假设我们有一个已定义的Optional,并且正在调用它的stream()方法。这将创建一个包含一个元素的Stream,我们可以在其上使用Stream API中可用的所有方法:

@Test
public void givenOptionalOfSome_whenToStream_thenShouldTreatItAsOneElementStream() {
    // given
    Optional<String> value = Optional.of("a");

    // when
    List<String> collect = value.stream().map(String::toUpperCase).collect(Collectors.toList());

    // then
    assertThat(collect).hasSameElementsAs(List.of("A"));
}

另一方面,如果Optional不存在,调用它的stream()方法将创建一个空的Stream:

@Test
public void givenOptionalOfNone_whenToStream_thenShouldTreatItAsZeroElementStream() {
    // given
    Optional<String> value = Optional.empty();

    // when
    List<String> collect = value.stream()
        .map(String::toUpperCase)
        .collect(Collectors.toList());

    // then
    assertThat(collect).isEmpty();
}

现在,我们可以快速过滤Optional流

对空Stream进行操作不会产生任何影响,但由于有了stream()方法,我们现在可以将Optional API与Stream API链接起来,这使我们能够创建更优雅、更流畅的代码。

5. 总结

在这篇简短的文章中,我们介绍了Java 9 Optional API的新增功能。

我们看到了如何使用or()方法在源Optional为空的情况下返回Optional。如果值存在,我们使用ifPresentOrElse()来执行消费者,否则运行另一个回调。

最后,我们看到了如何使用stream()方法将Optional与Stream API链接起来。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章