Optional orElse Optional – 可选或不选 可选

最后修改: 2018年 5月 27日

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

1. Introduction

1.介绍

In some cases, we might want to fallback to another Optional instance if another one is empty.

在某些情况下,如果另一个Optional实例是空的,我们可能想回退到另一个Optional实例。

In this tutorial, we’ll briefly mention how we can do that – which is harder than it looks.

在本教程中,我们将简要提及如何做到这一点–这比看起来更难。

For an introduction to the Java Optional class, have a look at our previous article.

关于Java可选类的介绍,请看我们的前文

2. Java 8

2.Java 8

In Java 8, there’s no direct way to achieve return a different Optional if the first one is empty.

在Java 8中,如果第一个选项为空,则没有直接的方法来实现返回不同的Optional

Therefore, we can implement our own custom method:

因此,我们可以实现我们自己的自定义方法。

public static <T> Optional<T> or(Optional<T> optional, Optional<T> fallback) {
    return optional.isPresent() ? optional : fallback;
}

And, in practice:

而且,在实践中。

@Test
public void givenOptional_whenValue_thenOptionalGeneralMethod() {
    String name = "Filan Fisteku";
    String missingOptional = "Name not provided";
    Optional<String> optionalString = Optional.ofNullable(name);
    Optional<String> fallbackOptionalString = Optional.ofNullable(missingOptional);
 
    assertEquals(
      optionalString, 
      Optionals.or(optionalString, fallbackOptionalString));
}
    
@Test
public void givenEmptyOptional_whenValue_thenOptionalGeneralMethod() {
    Optional<String> optionalString = Optional.empty();
    Optional<String> fallbackOptionalString = Optional.ofNullable("Name not provided");
 
    assertEquals(
      fallbackOptionalString, 
      Optionals.or(optionalString, fallbackOptionalString));
}

2.1. Lazy Evaluation

2.1.懒惰的评估

The above solution has one serious drawback – we need to evaluate both Optional variables before using our custom or() method.

上述解决方案有一个严重的缺点–我们需要在使用我们的自定义or()方法之前对两个Optional变量进行评估

Imagine, we have two methods returning Optionals, both querying database under the hood. It would be unacceptable, from the performance point of view, to call both of them if already the first method returns the value we need.

想象一下,我们有两个返回Optionals的方法,都是在引擎盖下查询数据库。从性能的角度来看,如果第一个方法已经返回了我们需要的值,那么同时调用这两个方法将是不可接受的。

Let’s create a simple ItemsProvider class:

让我们创建一个简单的ItemsProvider类。

public class ItemsProvider {
    public Optional<String> getNail(){
        System.out.println("Returning a nail");
        return Optional.of("nail");
    }

    public Optional<String> getHammer(){
        System.out.println("Returning a hammer");
        return Optional.of("hammer");
    }
}

Here’s how we can chain these methods and take advantage of lazy evaluation:

下面是我们如何链接这些方法并利用懒惰评估的优势

@Test
public void givenTwoOptionalMethods_whenFirstNonEmpty_thenSecondNotEvaluated() {
    ItemsProvider itemsProvider = new ItemsProvider();

    Optional<String> item = itemsProvider.getNail()
            .map(Optional::of)
            .orElseGet(itemsProvider::getHammer);

    assertEquals(Optional.of("nail"), item);
}

The above test case prints only “Returning a nail”. This clearly indicates that only the getNail() method has been executed.

上面的测试案例只打印了“返回一个钉子”。这清楚地表明,只有getNail()方法被执行了。

3. Java 9

3.JAVA 9

Java 9 has added an or() method that we can use to get an Optional, or another value, if that Optional isn’t present.

Java 9增加了一个or()方法,我们可以用它来获取一个Optional,或者另一个值,如果该Optional不存在

Let’s see this in practice with a quick example:

让我们通过一个简单的例子来看看这一点的实践。

public static Optional<String> getName(Optional<String> name) {
    return name.or(() -> getCustomMessage());
}

We’ve used an auxiliary method to help us with our example:

我们使用了一个辅助方法来帮助我们的例子。

private static Optional<String> getCustomMessage() {
    return Optional.of("Name not provided");
}

We can test it and further understand how it’s working. The following test case is a demonstration of the case when Optional has a value:

我们可以测试它,并进一步了解它的工作原理。下面的测试案例是对Optional有值时的情况的演示。

@Test
public void givenOptional_whenValue_thenOptional() {
    String name = "Filan Fisteku";
    Optional<String> optionalString = Optional.ofNullable(name);
    assertEquals(optionalString, Optionals.getName(optionalString));
}

4. Using Guava

4.使用番石榴

Another way to do this is by using or() method of the guava’s Optional class. First, we need to add guava in our project (the latest version can be found here):

另一种方法是通过使用guava的Optional类的or()方法来实现。首先,我们需要在我们的项目中添加guava(最新版本可以在这里)。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

Now, we can continue with the same example that we had earlier:

现在,我们可以继续之前的例子。

public static com.google.common.base.Optional<String> 
  getOptionalGuavaName(com.google.common.base.Optional<String> name) {
    return name.or(getCustomMessageGuava());
}
private static com.google.common.base.Optional<String> getCustomMessageGuava() {
    return com.google.common.base.Optional.of("Name not provided");
}

As we can see, it’s very similar to the one displayed above. However, it has a slight difference in the naming of the method and is exactly the same as or() method of the class Optional from JDK 9.

我们可以看到,它与上面显示的非常相似。然而,它在方法的命名上略有不同,与JDK 9中Optional 类的or() 方法完全相同。

We can now test it, similarly as the example above:

我们现在可以测试它,与上面的例子类似。

@Test
public void givenGuavaOptional_whenInvoke_thenOptional() {
    String name = "Filan Fisteku";
    Optional<String> stringOptional = Optional.of(name);
 
    assertEquals(name, Optionals.getOptionalGuavaName(stringOptional));
}
@Test
public void givenGuavaOptional_whenNull_thenDefaultText() {
    assertEquals(
      com.google.common.base.Optional.of("Name not provided"), 
      Optionals.getOptionalGuavaName(com.google.common.base.Optional.fromNullable(null)));
}

5. Conclusion

5.结论

This was a quick article illustrating how to achieve Optional orElse Optional functionality.

这是一篇快速文章,说明如何实现Optional orElse Optional功能。

The code for all the examples explained here, and much more can be found over on GitHub.

这里解释的所有例子的代码,以及更多的代码都可以在GitHub上找到