# Java 8 开始新增的 Optional 类 - Optional 在 Java 8 中的 Chaining 特性

**URL:** <https://www.isharkfly.com/t/java-8-optional-optional-java-8-chaining/13970>\
**Category:** 程序语言\
**Tags:** java\
**Created:** [May 13, 2022, 8:26pm UTC](https://www.isharkfly.com/t/java-8-optional-optional-java-8-chaining/13970 "2022-05-13T20:26:31Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![honeymoose](https://www.isharkfly.com/user_avatar/www.isharkfly.com/honeymoose/32/20796_2.png) [@honeymoose](https://www.isharkfly.com/u/honeymoose)\
**Post date:** [May 13, 2022, 8:26pm UTC](https://www.isharkfly.com/t/java-8-optional-optional-java-8-chaining/13970/1 "2022-05-13T20:26:31Z")

</div>

## Java 8 Optional 中的 Chaining 特性

有时候我们希望从一系列的 Optional 对象中找到第一个不为 Null 的 Optional 对象。

在上面的情况下，如果我们能够使用 `orElseOptional()` 方法的话，那就变得非常方便能够实现我们的需求了，但是这个没有办法在 Java 8 直接提供支持。

让我们首先看看有哪些方法我们能够使用来达到上面的目标。

```auto
private Optional<String> getEmpty() {
    return Optional.empty();
}

private Optional<String> getHello() {
    return Optional.of("hello");
}

private Optional<String> getBye() {
    return Optional.of("bye");
}

private Optional<String> createOptional(String input) {
    if (input == null || "".equals(input) || "empty".equals(input)) {
        return Optional.empty();
    }
    return Optional.of(input);
}

```

为了能够在 Java 8 中对一系列的 Optional 进行处理，并且返回第一个不为空的 Optional 对象，我们可以使用 Stream API 来做这件事情。

```auto
@Test
public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturned() {
    Optional<String> found = Stream.of(getEmpty(), getHello(), getBye())
      .filter(Optional::isPresent)
      .map(Optional::get)
      .findFirst();
    
    assertEquals(getHello(), found);
}

```

上面的方法有一个不是非常理想的情况就是不管 Steam 中的 Optional 对象是不是为空，`get()` 这个方法总是会被执行一次。

为了在 _Stream.of()_ 中进行更有效率的判读，我们需要在 Supplier 接口中使用方法的参考：

```auto
@Test
public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturnedAndRestNotEvaluated() {
    Optional<String> found =
      Stream.<Supplier<Optional<String>>>of(this::getEmpty, this::getHello, this::getBye)
        .map(Supplier::get)
        .filter(Optional::isPresent)
        .map(Optional::get)
        .findFirst();

    assertEquals(getHello(), found);
}

```

在这个用例中，我们需要使用接受参数的方法，同时在 lambda 中使用：

```auto
@Test
public void givenTwoOptionalsReturnedByOneArgMethod_whenChaining_thenFirstNonEmptyIsReturned() {
    Optional<String> found = Stream.<Supplier<Optional<String>>>of(
      () -> createOptional("empty"),
      () -> createOptional("hello")
    )
      .map(Supplier::get)
      .filter(Optional::isPresent)
      .map(Optional::get)
      .findFirst();

    assertEquals(createOptional("hello"), found);
}

```

同时，我们还希望在我们的 Optional 调用中返回一个默认的值，我们还可以添加一个 _orElse()_ 或者 _orElseGet()_ 方法：

```auto
@Test
public void givenTwoEmptyOptionals_whenChaining_thenDefaultIsReturned() {
    String found = Stream.<Supplier<Optional<String>>>of(
      () -> createOptional("empty"),
      () -> createOptional("empty")
    )
      .map(Supplier::get)
      .filter(Optional::isPresent)
      .map(Optional::get)
      .findFirst()
      .orElseGet(() -> "default");

    assertEquals("default", found);
}

```
