这是我到目前为止所得到的:
Optional<Foo> firstChoice = firstChoice();
Optional<Foo> secondChoice = secondChoice();
return Optional.ofNullable(firstChoice.orElse(secondChoice.orElse(null)));
这令我感到羞耻和浪费。如果firstChoice存在,我将不必要地计算secondChoice。
还有一个更有效的版本:
Optional<Foo> firstChoice = firstChoice();
if(firstChoice.isPresent()) {
return firstChoice;
} else {
return secondChoice();
}
在这里,我无法将一些映射函数链接到最终,而无需复制映射器或声明另一个局部变量。所有这些使得代码比实际解决的问题更复杂。
我更愿意写这个:
return firstChoice().alternatively(secondChoice());
然而,可选::显然不存在。现在怎么样?
答案 0 :(得分:40)
试试这个:
firstChoice().map(Optional::of)
.orElseGet(this::secondChoice);
map方法为您提供Optional<Optional<Foo>>
。然后,orElseGet
方法将其展平为Optional<Foo>
。仅当secondChoice
返回空的可选项时,才会评估firstChoice()
方法。
答案 1 :(得分:5)
您只需将其替换为
即可Optional<Foo> firstChoice = firstChoice();
return firstChoice.isPresent()? firstChoice : secondChoice();
除非 firstChoice.isPresent()为false,否则上述代码不会调用。
但是你必须准备调用这两个函数来获得所需的输出。没有其他方法可以逃避检查。
答案 2 :(得分:4)
也许是这样的:
Optional<String> finalChoice = Optional.ofNullable(firstChoice()
.orElseGet(() -> secondChoice()
.orElseGet(() -> null)));
答案 3 :(得分:4)
以下是@marstran解决方案对任意数量的选项的概括:
@SafeVarargs
public static <T> Optional<T> selectOptional(Supplier<Optional<T>>... optionals) {
return Arrays.stream(optionals)
.reduce((s1, s2) -> () -> s1.get().map(Optional::of).orElseGet(s2))
.orElse(Optional::empty).get();
}
测试:
public static Optional<String> first() {
System.out.println("foo called");
return Optional.empty();
}
public static Optional<String> second() {
System.out.println("bar called");
return Optional.of("bar");
}
public static Optional<String> third() {
System.out.println("baz called");
return Optional.of("baz");
}
public static void main(String[] args) {
System.out.println(selectOptional(() -> first(), () -> second(), () -> third()));
}
输出:
foo called
bar called
Optional[bar]
答案 4 :(得分:1)
我对java 8中不支持这个事实感到很沮丧,我转而回到番石榴的选项or
:
public abstract Optional<T> or(Optional<? extends T> secondChoice)
如果存在值,则返回此Optional;第二个选择。
答案 5 :(得分:0)
延迟计算和任意数量的Stream.<Supplier<Optional<Foo>>>of(
this::firstChoice,
this::secondChoice
).map(
Supplier::get
).filter(
Optional::isPresent
).findFirst(
).orElseGet(
Optional::empty
);
元素
{{1}}
答案 6 :(得分:-1)
这是一种适用于基于流API的任意数量Optional
的方法:
return Arrays.asList(firstChoice, secondChoice).stream()
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst().orElse(null);
它不是最短的。但更简单易懂。
另一种方法是使用来自Guava of commons-lang的firstNonNull()
,如果你已经使用了其中一个库:
firstNonNull(firstChoice.orElse(null), secondChoice.orElse(null));