如何在Java 8中实现Elvis运算符?

Mic*_*lot 11 java functional-programming optional java-8

我有经典的"Elvis运算符"案例,我在这里调用方法,每个方法都可以返回null并将它们链接在一起:

thing?:nullableMethod1(a)?:nullableMethod2(b)?:nullableMethod3()
Run Code Online (Sandbox Code Playgroud)

在Java 8中,我发现的最忠实的实现是这样的:

return Optional.ofNullable(thing)
    .flatMap(x -> Optional.ofNullable(x.nullableMethod1(a)))
    .flatMap(y -> Optional.ofNullable(y.nullableMethod2(b)))
    .flatMap(z -> Optional.ofNullable(z.nullableMethod3()))
Run Code Online (Sandbox Code Playgroud)

我希望Java Optional有类似于elvis运算符的东西:

public<U> Optional<U> elvisOperator(Function<? super T, ? extends U> mapper) {
    return flatMap(t -> Optional.ofNullable(mapper.apply(t));
}
Run Code Online (Sandbox Code Playgroud)

这样我就不必包装每个返回值:

return Optional.ofNullable(thing)
    .elvisOperator(x -> x.nullableMethod1(a))
    .elvisOperator(y -> y.nullableMethod2(b))
    .elvisOperator(Z::nullableMethod3); // also nice
Run Code Online (Sandbox Code Playgroud)

在Java 8中实现Elvis运算符模式是否有更高效和惯用的方法?

Jac*_* G. 13

也许我忽视了一些事情,但是有一个你不能使用的理由Optional#map吗?

下面的例子打印任何东西,因为Optional短路在这个意义上,如果里面的值Optional不存在(它null或者Optional是空的),它会被视为空.

Optional.ofNullable("test")
        .map(s -> null)
        .ifPresent(System.out::println);
Run Code Online (Sandbox Code Playgroud)

因此,我认为您可以执行以下操作:

return Optional.ofNullable(thing)
               .map(x -> x.nullableMethod1(a))
               .map(y -> y.nullableMethod2(b))
               .map(Z::nullableMethod3);
Run Code Online (Sandbox Code Playgroud)

这将映射您thing是否存在,否则返回空Optional.

  • 值得一提的是[`Optional.map`的文档](https://docs.oracle.com/javase/10/docs/api/java/util/Optional.html#map(java.util.function.Function )) 来表明该行为是有意为之:“*如果映射函数返回一个 `null` 结果,则此方法返回一个空的 `Optional`*”。 (3认同)
  • @Holger 和 [this](https://developer.atlassian.com/blog/2015/08/optional-broken/) 解释了为什么从长远来看这是个坏主意。或者,至少是次优的(从 FP 的角度来看)。 (2认同)

Abh*_*kar 8

在 Java 8 中,Elvis 操作符可以通过链接.map(...)对 an 的调用来模拟,Optional.ofNullable(...)并用 来限制它.orElse(...)

Optional.ofNullable(dataObject)
.map(DataObject::getNestedDataObject)
.map(NestedDataObject::getEvenMoreNestedDataObject)
...
.orElse(null);
Run Code Online (Sandbox Code Playgroud)

一个完整的例子:

Optional.ofNullable(dataObject)
.map(DataObject::getNestedDataObject)
.map(NestedDataObject::getEvenMoreNestedDataObject)
...
.orElse(null);
Run Code Online (Sandbox Code Playgroud)