Javaで複数のメソッドの戻り値の最初の非null値を取得するエレガントな方法はありますか?

シムニン:

あなたはすでにこれを何度も自分で見たことがあります。

public SomeObject findSomeObject(Arguments args) {
    SomeObject so = queryFirstSource(args); // the most likely source first, hopefully
    if (so != null) return so;

    so = querySecondSource(args); // a source less likely than the first, hopefully
    if (so != null) return so;

    so = queryThirdSource(args); // a source less likely than the previous, hopefully
    if (so != null) return so;

    // and so on
}

検索するオブジェクトのソースはさまざまです。より鮮明な例として、ユーザーIDが特権ユーザーのリストにあるかどうかを最初に確認することをイメージできます。そうでない場合は、useridが許可されたユーザーのリストにあるかどうかを確認します。それ以外の場合はnullを返します。(これは最良の例ではありませんが、鮮明で十分なものであることを願っています。)

グアバは、上記のコードを美化できるいくつかのヘルパーを提供してくれます:

public SomeObject findSomeObject(Arguments args) {
    // if there are only two objects
    return com.google.common.base.Objects.firstNonNull(queryFirstSource(args), querySecondSource(args));

    // or else
    return com.google.common.collect.Iterables.find(
        Arrays.asList(
            queryFirstSource(args)
            , querySecondSource(args)
            , queryThirdSource(args)
            // , ...
        )
        , com.google.common.base.Predicates.notNull()
    );
 }

しかし、私たちの間で経験を積んだ人はすでに見てきたように、ルックアップ(つまりqueryXXXXSource(args))に一定の時間がかかる場合、パフォーマンスが低下する可能性がありますこれは、最初にすべてのソースにクエリを実行し、結果をメソッドに渡して、それらの結果の中で最初ではないを見つけるためnullです。

前者が何かを返さない場合にのみ次のソースが評価される最初の例とは対照的に、この2番目のソリューションは、最初は見栄えがよくなるかもしれませんが、パフォーマンスが大幅に低下する可能性があります。

ここで私が実際の質問に行き、誰かがすでにそのベースを実装していることを望んでいるか、または誰かがさらにスマートなソリューションを提案するかもしれないことを提案します。

平易な英語で:誰かがすでにそのようなdefferedFirstNonNull(以下を参照)または同様の何かを実装していますか?新しいStreamフレームワークでこれを実現する簡単なプレーンJavaソリューションはありますか?同じ結果を達成する別のエレガントなソリューションを提案できますか?

ルール: Java 8は許可されていますが、GoogleのGuavaやApacheのCommons Langなどのアクティブな維持された有名なサードパーティライブラリもApacheライセンスまたは同様のもの(GPLなし)で使用できます。

提案されたソリューション:

public SomeObject findSomeObject(Arguments args) {
    return Helper.deferredFirstNonNull(
        Arrays.asList(
            args -> queryFirstSource(args)
            , args -> querySourceSource(args)
            , args -> queryThirdSource(args)
        )
        , x -> x != null
     )
 }

したがって、メソッドdefferedFirstNonNullは各ラムダ式を次々に評価し、述語(x -> x != null)が真(つまり、一致が見つかった)とすぐに、メソッドはすぐに結果を返し、それ以上のソースを照会しません。

PS:式args -> queryXXXXSource(args)はに短縮できることは知っていますqueryXXXXSourceしかし、何が起こるかは一目で明らかではないため、提案されたソリューションは読みにくくなります。

ホルガー:

それはあなたが定義していないいくつかの要因に依存します。query…Source質問に示されているように、固定された、かなり小さいアクションのセットがありますか、それとも、より柔軟で拡張可能なアクションのリストを作成することを目指していますか?

最初のケースでは、query…Sourceメソッドを変更してまたはでOptional<SomeObject>なくを返すことを検討しますメソッドを次のように変更した場合SomeObjectnull

Optional<SomeObject> queryFirstSource(Arguments args) {
    …
}

あなたはこのようにそれらを連鎖させることができます:

public SomeObject findSomeObject(Arguments args) {
    return queryFirstSource(args).orElseGet(
      ()->querySecondSource(args).orElseGet(
      ()->queryThirdSource(args).orElse(null)));
}

それらを変更できない場合、または返すnullことを優先する場合でも、Optionalクラスを使用できます

public SomeObject findSomeObject(Arguments args) {
    return Optional.ofNullable(queryFirstSource(args)).orElseGet(
       ()->Optional.ofNullable(querySecondSource(args)).orElseGet(
       ()->queryThirdSource(args)));
}

可能性のあるクエリの数を増やすためのより柔軟な方法を探している場合、それらをある種のリストまたはのストリームに変換することは避けられませんFunction1つの可能な解決策は次のとおりです。

public SomeObject findSomeObject(Arguments args) {
    return Stream.<Function<Arguments,SomeObject>>of(
      this::queryFirstSource, this::querySecondSource, this::queryThirdSource
    ).map(f->f.apply(args)).filter(Objects::nonNull).findFirst().orElse(null);
}

これにより目的の操作が実行されますが、メソッドを呼び出すたびに必要なアクションが構成されます。このメソッドをより頻繁に呼び出したい場合は、再利用できる操作を作成することを検討してください。

Function<Arguments, SomeObject> find = Stream.<Function<Arguments,SomeObject>>of(
    this::queryFirstSource, this::querySecondSource, this::queryThirdSource
).reduce(a->null,(f,g)->a->Optional.ofNullable(f.apply(a)).orElseGet(()->g.apply(a)));

public SomeObject findSomeObject(Arguments args) {
    return find.apply(args);
}

つまり、1つ以上の方法があります。そして、それは実際のタスクがどの方向に進むかによります。場合によっては、単純なifシーケンスでも適切場合があります。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

メソッドからの戻り値を別のメソッドで使用する方法はありますか?

分類Dev

メソッドに複数の戻り値を持つ複数のifステートメントが含まれている場合に、メソッドから戻り値を取得するにはどうすればよいですか?

分類Dev

Java:prepareStatmentのよりエレガントな方法で複数の値を挿入する方法は?

分類Dev

Luaの複数の戻り値関数で戻り値をエレガントに参照するにはどうすればよいですか?

分類Dev

Javaで完全修飾の戻り値の型とメソッド名なしで特定の戻り値の型とメソッド名のみを取得する方法

分類Dev

テンプレートクラスからのメソッドの戻り値の型をtypedefする方法は?

分類Dev

GNU Octaveアサートテストメソッドで複数の戻り値をテストする方法は?

分類Dev

Python:スレッド関数から複数の戻り値を取得する方法

分類Dev

AndroidのFirebaseCloud Functions onCallメソッドから戻り値を取得する適切な方法は何ですか?

分類Dev

Javaで複数のランダムな値を取得する簡単な方法はありますか?

分類Dev

行列の各行のtop [2〜3]値のみを保持するエレガントな方法はありますか?

分類Dev

複数のスレッドでメソッドの戻り値を収集する方法

分類Dev

Pythonで既存のオブジェクトにメソッドを追加するエレガントな方法はありますか?

分類Dev

このコードよりもJavaでXMLドキュメントを文字列に変換するよりエレガントな方法はありますか?

分類Dev

C#で非静的メソッドからの戻り値を表示する方法

分類Dev

Java文字列とメソッドの戻り値を出力するとき、メソッドが最初に出力を返すのはなぜですか?

分類Dev

実際の値を割り当てたばかりのnull許容フィールドはもうnullにできないことをコンパイラに納得させる、エレガントなkotlinの方法はありますか?

分類Dev

現在のコードよりも、複数の非表示のdivでjquery .slideToggleを使用するためのよりエレガントでシンプルな方法はありますか?

分類Dev

メソッド内のメソッドから戻り値を取得する方法

分類Dev

メソッドの戻り値を変数に割り当てる必要がないのはなぜですか?

分類Dev

コードを読みやすくするためにJavaブール値の名前を変更するエレガントな方法はありますか?

分類Dev

Python関数のいくつかの戻り値をエレガントに無視する方法は?

分類Dev

複数のリストの最後の値を削除するよりエレガントな方法は?

分類Dev

テストでプライベートメソッドの戻り値から値を取得する方法

分類Dev

mockito:スタブメソッドの戻り値をキャプチャする方法はありますか?

分類Dev

テンプレートパラメータメソッドの戻り値の型を取得するにはどうすればよいですか?

分類Dev

あるメソッドが別のメソッドのジェネレーターから次の値を取得する方法はありますか?

分類Dev

引数に基づいてRust関数またはトレイトメソッドの戻り値の型を計算することは可能ですか?

分類Dev

Marklogicのクエリコンソールでパス範囲インデックスの戻り値をテストする方法はありますか?

Related 関連記事

  1. 1

    メソッドからの戻り値を別のメソッドで使用する方法はありますか?

  2. 2

    メソッドに複数の戻り値を持つ複数のifステートメントが含まれている場合に、メソッドから戻り値を取得するにはどうすればよいですか?

  3. 3

    Java:prepareStatmentのよりエレガントな方法で複数の値を挿入する方法は?

  4. 4

    Luaの複数の戻り値関数で戻り値をエレガントに参照するにはどうすればよいですか?

  5. 5

    Javaで完全修飾の戻り値の型とメソッド名なしで特定の戻り値の型とメソッド名のみを取得する方法

  6. 6

    テンプレートクラスからのメソッドの戻り値の型をtypedefする方法は?

  7. 7

    GNU Octaveアサートテストメソッドで複数の戻り値をテストする方法は?

  8. 8

    Python:スレッド関数から複数の戻り値を取得する方法

  9. 9

    AndroidのFirebaseCloud Functions onCallメソッドから戻り値を取得する適切な方法は何ですか?

  10. 10

    Javaで複数のランダムな値を取得する簡単な方法はありますか?

  11. 11

    行列の各行のtop [2〜3]値のみを保持するエレガントな方法はありますか?

  12. 12

    複数のスレッドでメソッドの戻り値を収集する方法

  13. 13

    Pythonで既存のオブジェクトにメソッドを追加するエレガントな方法はありますか?

  14. 14

    このコードよりもJavaでXMLドキュメントを文字列に変換するよりエレガントな方法はありますか?

  15. 15

    C#で非静的メソッドからの戻り値を表示する方法

  16. 16

    Java文字列とメソッドの戻り値を出力するとき、メソッドが最初に出力を返すのはなぜですか?

  17. 17

    実際の値を割り当てたばかりのnull許容フィールドはもうnullにできないことをコンパイラに納得させる、エレガントなkotlinの方法はありますか?

  18. 18

    現在のコードよりも、複数の非表示のdivでjquery .slideToggleを使用するためのよりエレガントでシンプルな方法はありますか?

  19. 19

    メソッド内のメソッドから戻り値を取得する方法

  20. 20

    メソッドの戻り値を変数に割り当てる必要がないのはなぜですか?

  21. 21

    コードを読みやすくするためにJavaブール値の名前を変更するエレガントな方法はありますか?

  22. 22

    Python関数のいくつかの戻り値をエレガントに無視する方法は?

  23. 23

    複数のリストの最後の値を削除するよりエレガントな方法は?

  24. 24

    テストでプライベートメソッドの戻り値から値を取得する方法

  25. 25

    mockito:スタブメソッドの戻り値をキャプチャする方法はありますか?

  26. 26

    テンプレートパラメータメソッドの戻り値の型を取得するにはどうすればよいですか?

  27. 27

    あるメソッドが別のメソッドのジェネレーターから次の値を取得する方法はありますか?

  28. 28

    引数に基づいてRust関数またはトレイトメソッドの戻り値の型を計算することは可能ですか?

  29. 29

    Marklogicのクエリコンソールでパス範囲インデックスの戻り値をテストする方法はありますか?

ホットタグ

アーカイブ