Optional.orElse() と Optional.orElseGet() の違い 質問する

Optional.orElse() と Optional.orElseGet() の違い 質問する

私は、Optional<T>.orElse()そしてOptional<T>.orElseGet()方法。

メソッドの説明は次のorElse()とおりです。

存在する場合は値を返し、そうでない場合はその他を返します。

一方、メソッドの説明は次のとおりorElseGet()です。

値が存在する場合はその値を返し、存在しない場合は other を呼び出してその呼び出しの結果を返します。

このorElseGet()メソッドは、基本的にパラメータを一切受け取らずに を返す Supplier 機能インターフェースを受け取りますT

どのような状況で を使用する必要がありますかorElseGet()? メソッドがある場合、 ではなく をT myDefault()実行しないのはなぜですか?optional.orElse(myDefault())optional.orElseGet(() -> myDefault())

ラムダ式の実行を後で延期しているようには見えないのでorElseGet()、その意味は何でしょうか? ( をスローせず常に true を返すより安全な を返せばもっと便利だと思ったのですが、Optional<T>どうやらget()そうNoSuchElementExceptionではなく、のようにisPresent()返されるだけです)。TorElse()

私が見逃している他の違いはありますか?

ベストアンサー1

短い答え:

  • orElse() はOptional.isPresent()、値に関係なく、希望するかどうかに関係なく、常に指定された関数を呼び出します。
  • orElseGet()は、指定された関数を呼び出すのは、Optional.isPresent() == false

実際のコードでは、必要なリソースの取得にコストがかかる場合は、2 番目のアプローチを検討する必要があります。

// Always get heavy resource
getResource(resourceId).orElse(getHeavyResource()); 

// Get heavy resource when required.
getResource(resourceId).orElseGet(() -> getHeavyResource()) 

詳細については、この関数を使用した次の例を参照してください。

public Optional<String> findMyPhone(int phoneId)

違いは以下のとおりです。

                           X : buyNewExpensivePhone() called

+——————————————————————————————————————————————————————————————————+——————————————+
|           Optional.isPresent()                                   | true | false |
+——————————————————————————————————————————————————————————————————+——————————————+
| findMyPhone(int phoneId).orElse(buyNewExpensivePhone())          |   X  |   X   |
+——————————————————————————————————————————————————————————————————+——————————————+
| findMyPhone(int phoneId).orElseGet(() -> buyNewExpensivePhone()) |      |   X   |
+——————————————————————————————————————————————————————————————————+——————————————+

の場合optional.isPresent() == false、2 つの方法に違いはありません。ただし、 の場合optional.isPresent() == trueorElse()必要かどうかに関係なく、常に後続の関数が呼び出されます。

最後に、使用したテストケースは以下のとおりです。

結果:

------------- Scenario 1 - orElse() --------------------
  1.1. Optional.isPresent() == true (Redundant call)
    Going to a very far store to buy a new expensive phone
    Used phone: MyCheapPhone

  1.2. Optional.isPresent() == false
    Going to a very far store to buy a new expensive phone
    Used phone: NewExpensivePhone

------------- Scenario 2 - orElseGet() --------------------
  2.1. Optional.isPresent() == true
    Used phone: MyCheapPhone

  2.2. Optional.isPresent() == false
    Going to a very far store to buy a new expensive phone
    Used phone: NewExpensivePhone

コード:

public class TestOptional {
    public Optional<String> findMyPhone(int phoneId) {
        return phoneId == 10
                ? Optional.of("MyCheapPhone")
                : Optional.empty();
    }

    public String buyNewExpensivePhone() {
        System.out.println("\tGoing to a very far store to buy a new expensive phone");
        return "NewExpensivePhone";
    }


    public static void main(String[] args) {
        TestOptional test = new TestOptional();
        String phone;
        System.out.println("------------- Scenario 1 - orElse() --------------------");
        System.out.println("  1.1. Optional.isPresent() == true (Redundant call)");
        phone = test.findMyPhone(10).orElse(test.buyNewExpensivePhone());
        System.out.println("\tUsed phone: " + phone + "\n");

        System.out.println("  1.2. Optional.isPresent() == false");
        phone = test.findMyPhone(-1).orElse(test.buyNewExpensivePhone());
        System.out.println("\tUsed phone: " + phone + "\n");

        System.out.println("------------- Scenario 2 - orElseGet() --------------------");
        System.out.println("  2.1. Optional.isPresent() == true");
        // Can be written as test::buyNewExpensivePhone
        phone = test.findMyPhone(10).orElseGet(() -> test.buyNewExpensivePhone());
        System.out.println("\tUsed phone: " + phone + "\n");

        System.out.println("  2.2. Optional.isPresent() == false");
        phone = test.findMyPhone(-1).orElseGet(() -> test.buyNewExpensivePhone());
        System.out.println("\tUsed phone: " + phone + "\n");
    }
}

おすすめ記事