ここに私がこれまでに得たものがあります:
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());
ただし、Optional :: Alternativelyは存在しません。それで?
これを試して:
_firstChoice().map(Optional::of)
.orElseGet(this::secondChoice);
_
Mapメソッドは_Optional<Optional<Foo>>
_を提供します。次に、orElseGet
メソッドはこれを_Optional<Foo>
_にフラット化します。 secondChoice
メソッドは、firstChoice()
が空のオプションを返す場合にのみ評価されます。
それを単に置き換えることができます、
Optional<Foo> firstChoice = firstChoice();
return firstChoice.isPresent()? firstChoice : secondChoice();
firstChoice.isPresent()がfalseでない限り、上記のコードは呼び出されません。
ただし、目的の出力を取得するには、両方の関数を呼び出す準備をする必要があります。チェックを回避する方法は他にありません。
任意の数のオプションに対する@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]
たぶんこのようなもの:
Optional<String> finalChoice = Optional.ofNullable(firstChoice()
.orElseGet(() -> secondChoice()
.orElseGet(() -> null)));
これがJava 8でサポートされていなかったという事実に十分イライラしていました。つまり、 or
:
public abstract Optional<T> or(Optional<? extends T> secondChoice)
値が存在する場合、このOptionalを返します。それ以外の場合はsecondChoice。
遅延計算と任意の数のOptional
要素
Stream.<Supplier<Optional<Foo>>>of(
this::firstChoice,
this::secondChoice
).map(
Supplier::get
).filter(
Optional::isPresent
).findFirst(
).orElseGet(
Optional::empty
);