web-dev-qa-db-ja.com

1つのオプションまたは別の値を取得します

2つの_Java.util.Optional_インスタンスがあり、次のいずれかのOptionalを取得したい:

  • 値がある場合、最初のオプションの値を持ちます。
  • 2番目のオプションの値があります(値がある場合)。
  • どちらも空ではないOptionalには値があります。

それを行う簡単な方法はありますか?つまり、それを行うためのAPIがすでにありますか?

次の式でそれを行いますが、最初のオプションは2回言及する必要があります。

_firstOptional.isPresent() ? firstOptional : secondOptional
_

これはcom.google.common.base.Optional.or()が行うこととまったく同じですが、そのメソッドはJava 8のAPIには存在しません。


aioobeによって受け入れられた回答には、このようなOptional AP​​Iの省略を克服するためのいくつかの代替アプローチがリストされています。コードベースにユーティリティ関数を追加することにしました:

_public static <T> Optional<T> or(Optional<T> a, Optional<T> b) {
    if (a.isPresent())
        return a;
    else
        return b;
}
_
45
Feuermurmel

更新:Java 9( changeset 12885 )の時点でできること

firstOptional.or(() -> secondOptional);

Java 8、続きを読む...

firstOptionalに2回言及することを避けたい場合は、おそらく次のようなものを使用する必要があります。

firstOptional.map(Optional::of).orElse(secondOptional);

または

Optional.ofNullable(firstOptional.orElse(secondOptional.orElse(null)));

しかし、最も読みやすいバリアントは、おそらく単純に

Optional<...> opt = firstOptional.isPresent()  ? firstOptional
                  : secondOptional.isPresent() ? secondOptional
                  : Optional.empty();

誰かがこの質問に出くわしたが、オプションのlistがある場合は、次のようなものをお勧めします

Optional<...> opt = optionals.stream()
                             .filter(Optional::isPresent)
                             .findFirst()
                             .orElse(Optional.empty());
57
aioobe

EDIT:もともとGuavaのOptionalを使用していると思いました。回答を更新して、それぞれのOptionalクラスにGuavaとJava 8構文の両方を提供します。

Java 8オプション

これまで短縮できます:

_firstOptional.orElse(secondOptional.orElse(EMPTY_VALUE))
_

「空」という3番目の箇条書きの意味はわかりません。 nullを意味する場合、これはトリックを行います:

_firstOptional.orElse(secondOptional.orElse(null))
_

orElse()Optionalのメソッドであり、存在する場合は値を返します。それ以外の場合は、orElse()の引数として指定した値を返します。

グアバオプション

これまで短縮できます:

_firstOptional.or(secondOptional.or(EMPTY_VALUE))
_

「空」という3番目の箇条書きの意味はわかりません。 nullを意味する場合、これはトリックを行います:

_firstOptional.or(secondOptional.orNull())
_

or()Optionalのメソッドであり、存在する場合は値を返します。それ以外の場合は、or()の引数として指定した値を返します。

8
Erik Gillespie

JDK 9で解決された可能性のある問題に何度か遭遇しましたOptional::orそして、JDK 8を使用しているためできませんでした。最後に、このメソッドでutilクラスを追加しました。

@SafeVarargs
public static <T> Optional<T> firstPresent(final Supplier<Optional<T>>... optionals) {
    return Stream.of(optionals)
            .map(Supplier::get)
            .filter(Optional::isPresent)
            .findFirst()
            .orElse(Optional.empty());
}

これで、このメソッドに任意の数のオプションを提供でき、次のように遅延評価されます。

    final Optional<String> username = OptionalUtil.firstPresent(
            () -> findNameInUserData(user.getBasicData()),
            () -> findNameInUserAddress(user.getAddress()),
            () -> findDefaultUsername());

現在、findNameInUserAddressは、findNameInUserDataが空を返す場合にのみ呼び出されます。 findDefaultUsernamefindNameInUserDataの両方が空などを返す場合にのみ、findNameInUserAddressが呼び出されます。

7
jahmaican