如何在Java8中实现Elvis操作符?

如何在Java8中实现Elvis操作符?,java,java-8,functional-programming,optional,Java,Java 8,Functional Programming,Optional,我有一个经典的“Elvis运算符”案例,我调用了每个方法都可能返回null并将它们链接在一起: thing?:nullableMethod1(a)?:nullableMethod2(b)?:nullableMethod3() 在Java 8中,我发现最忠实的实现如下: return Optional.ofNullable(thing) .flatMap(x -> Optional.ofNullable(x.nullableMethod1(a))) .flatMap(y -

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

thing?:nullableMethod1(a)?:nullableMethod2(b)?:nullableMethod3()
在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()))
我希望Java的
可选
具有类似于elvis操作符的功能:

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

有没有一种更有效、更惯用的方法来实现Java 8中的Elvis操作符模式?

也许我忽略了一些东西,但是有没有一个原因让你不能使用
可选的35; map

以下示例不打印任何内容,因为
Optional
是短路,即如果
Optional
中的值不存在(为
null
Optional
为空),则将其视为空

Optional.ofNullable("test")
        .map(s -> null)
        .ifPresent(System.out::println);
因此,我认为你可以做以下几点:

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

这将映射您的
对象
,如果它存在,或者返回一个空的
可选的

在Java 8中,可以通过链接
.map(…)
调用
可选的.ofNullable(…)
并用
覆盖它。orElse(…)

一个完整的例子:

import java.util.Optional;
班长{
//数据类:
静态类动物{
腿;
动物(腿){
这个腿=腿;
}
Leg getLeg(){返回this.Leg;}
公共字符串toString(){
String out=“这是一种动物”;
out+=支腿!=空?“带支腿”:“”;
返回;
}
}
静态类腿{
脚趾;
腿(脚趾){
这个。脚趾=脚趾;
}
Toes GETOES(){返回this.Toes;}
公共字符串toString(){
String out=“这是一条腿”;
out+=toes!=null?“带有一组toes:”;
返回;
}
}
静态类脚趾{
整数整数;
脚趾(整数numToes){
this.numToes=numToes;
}
整数getNumToes(){返回this.numToes;}
公共字符串toString(){
String out=“这是一个集合”;
out+=numToes!=null&&numToes>0?numToes:“否”;
out+=“脚趾”;
返回;
}
}
//Elvis运算符的几个示例:
静态整数getNumToesOrNull(动物a){
返回可选。不可用(a)
.map(动物::getLeg)
.map(Leg::getToes)
.map(Toes::getNumToes)
.orElse(空);
}
静态脚趾getToesOrNull(动物a){
返回可选。不可用(a)
.map(动物::getLeg)
.map(Leg::getToes)
.orElse(空);
}
静态支腿getLegOrNull(动物a){
返回可选。不可用(a)
.map(动物::getLeg)
.orElse(空);
}
//主要功能:
公共静态void main(字符串[]args){
//正在尝试访问“numToes”:
System.out.println(getNumToesOrNull(新动物(新腿(新脚趾)(4 '));//4
System.out.println
System.out.println(getNumToesOrNull(新动物(新腿(null)));//null
System.out.println(getNumToesOrNull(新动物(null));//null
System.out.println(getNumToesOrNull(null));//null
//正在尝试访问“脚趾”:
System.out.println(getToesOrNull(新动物(新腿)(新脚趾(4‘‘‘‘));//这是4个脚趾的集合
System.out.println(getToesOrNull(新动物(新腿)(新脚趾(null‘‘‘)’);//这是一个没有脚趾的集合
System.out.println(getToesOrNull(新动物(新腿(null)));//null
System.out.println(getToesOrNull(新动物(null));//null
System.out.println(getToesOrNull(null));//null
//正在尝试访问“leg”:
System.out.println(getLegOrNull(新动物(新腿)(新脚趾(4 ')));//这是一条有脚趾集合的腿
System.out.println(getLegOrNull(新动物(新腿)(新脚趾(null ')));//这是一条包含脚趾集合的腿
System.out.println(getLegOrNull(新动物)(新腿(null));//这是一条腿
System.out.println(getLegOrNull(新动物(null));//null
System.out.println(getLegOrNull(null));//null
}
}

值得指出的是,该行为是故意的:“如果映射函数返回一个
null
结果,那么该方法返回一个空的
可选的
”@Holger,并解释了为什么从长远来看,这是一个坏主意。或者,至少是次优的(从FP的角度来看)。他们实现了一个非常重要的功能,但出于某种原因,决定在这个过程中严重破坏可靠的旧地图。如果他们真的将第二种方法命名为“elvis”,那么就更容易原谅了。我想你在接受的答案中添加的是,一些语言模糊了可选性和可空性的概念,这样就可以使用elvis运算符,而无需在最后解包结果。在Java中,方法实现有时会模糊这些概念,但类型系统有不同的概念,所以是的,如果想要一个@Nullable Foo而不是一个可选的,那么最后很可能想要使用orElse。@Mickalot是的,这就是我想说的。我已经看到了一些其他的答案,并且对如何在没有
可选项的情况下进行操作感到困惑,直到我尝试了这个示例。我认为这可能对其他人有利。
return Optional.ofNullable(thing)
               .map(x -> x.nullableMethod1(a))
               .map(y -> y.nullableMethod2(b))
               .map(Z::nullableMethod3);
Optional.ofNullable(dataObject)
.map(DataObject::getNestedDataObject)
.map(NestedDataObject::getEvenMoreNestedDataObject)
...
.orElse(null);