Contents

Java 9 Optional简介

1. 概述

在本文中,我们将着眼于*可选 * API 的 Java 9 新增功能。 除了模块化之外,Java 9 还为Optional类添加了三个非常有用的方法。

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);
}

Optionalnull的情况下,返回的结果将与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实例时,我们通常希望对它的底层值执行特定的操作。另一方面,如果Optionalnull,我们希望记录它或通过增加一些指标来跟踪该事实。 ifPresentOrElse()方法正是为此类场景创建的。我们可以传递一个Consumer,如果Optional被定义就会被调用,Runnable会在Optional为空时被执行。

假设我们有一个已定义的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();
}

我们现在可以快速过滤OptionalsStreams

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