Java 9 Optional API Additions – Java 9 可选的 API 补充

最后修改: 2017年 6月 1日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we will be looking at the Java 9 additions to the Optional API.

在这篇文章中,我们将探讨Java 9对OptionalAPI的补充。

Beyond modularity, Java 9 is also adding three very useful methods for the Optional class.

除了模块化,Java 9还为Optional类增加了三个非常有用的方法。

2. The or() Method

2.or()方法

Sometimes, when our Optional is empty, we want to execute some other action that also returns an Optional.

有时,当我们的Optional是空的,我们想执行一些其他的动作,这些动作也会返回一个OOptional。

Prior Java 9 the Optional class had only the orElse() and orElseGet() methods but both need to return unwrapped values.

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

Java 9 introduces the or() method that returns another Optional lazily if our Optional is empty. If our first Optional has a defined value, the lambda passed to the or() method will not be invoked, and value will not be calculated and returned:

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

In the case of Optional being empty, the returned result will be the same as the defaultValue:

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. The ifPresentOrElse() Method

3.The ifPresentOrElse()Method

When we have an Optional instance, often we want to execute a specific action on the underlying value of it. On the other hand, if the Optional is empty we want to log it or track that fact by incrementing some metric.

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

The ifPresentOrElse() method is created exactly for such scenarios. We can pass a Consumer that will be invoked if the Optional is defined, and Runnable that will be executed if the Optional is empty.

ifPresentOrElse() 方法正是为这种情况而创建的。我们可以传递一个Consumer,如果Optional被定义,它将被调用;如果Optional为空,Runnable将被执行。

Let’s say that we have a defined Optional and we want to increment a specific counter if the value is present:

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

Note, that the callback passed as the second argument was not executed.

注意,作为第二个参数传递的回调没有被执行。

In the case of an empty Optional, the second callback gets executed:

如果是空的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. The stream() Method

4、stream()方法

The last method, which is added to the Optional class in the Java 9, is the stream() method.

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

Java has a very fluent and elegant Stream API that can operate on the collections and utilizes many functional programming concepts. The newest Java version introduces the stream() method on the Optional class that allows us to treat the Optional instance as a Stream.

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

Let’s say that we have a defined Optional and we are calling the stream() method on it. This will create a Stream of one element on which we can use all the methods that are available in the Stream API:

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

On the other hand, if Optional is not present, calling the stream() method on it will create an empty Stream:

另一方面,如果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();
}

We can now quickly filter Streams of Optionals.

我们现在可以快速过滤选项。

Operating on the empty Stream will not have any effect, but thanks to the stream() method we can now chain the Optional API with the Stream API. This allows us to create more elegant and fluent code.

在空的Stream上操作不会有任何效果,但是由于stream()方法,我们现在可以将OptionalAPI与StreamAPI链接起来。这使我们能够创建更优雅和流畅的代码。

5. Conclusion

5.结论

In this quick article, we looked at the Java 9 Optional API additions.

在这篇快速文章中,我们研究了Java 9 Optional API的新增内容。

We saw how to use the or() method to return an Optional in case if the source Optional is empty. We used the ifPresentOrElse() to execute the Consumer if the value is present and otherwise, run the another callback.

我们看到如何使用or() 方法在源Optional为空时返回一个Optional。我们使用ifPresentOrElse()来执行Consumer,如果值是存在的,则运行另一个回调。

Finally, we saw how to chain the Optional with the Stream API using the stream() method.

最后,我们看到了如何使用stream()方法将OptionalStreamAPI进行连锁。

The implementation of all these examples and code snippets can be found in the GitHub project – this is a Maven project, so it should be easy to import and run as it is.

所有这些例子和代码片段的实现都可以在GitHub项目中找到–这是一个Maven项目,所以应该很容易导入并按原样运行。