1. 序章

オプションのAPIには通常、混乱を引き起こす可能性のある2つのメソッド orElse() orElseGet()があります。

このクイックチュートリアルでは、これら2つの違いを確認し、それぞれをいつ使用するかを検討します。

2. 署名

まず、署名を見て基本から始めましょう。

public T orElse(T other)

public T orElseGet(Supplier<? extends T> other)

明らかに、 orElse()はタイプ Tの任意のパラメーターを取りますが、 orElseGet()はタイプサプライヤーの機能インターフェースを受け入れます。タイプTのオブジェクト。

Javadocs に基づく:

  • orElse():存在する場合は値を返し、存在しない場合はotherを返します。
  • orElseGet():は、存在する場合は値を返し、そうでない場合は other を呼び出し、その呼び出しの結果を返します

3. 違い

これらの単純化された定義に少し混乱するのは簡単なので、もう少し深く掘り下げて、実際の使用シナリオをいくつか見てみましょう。

3.1. orElse()

ロガーが適切に構成されていると仮定して、簡単なコードの記述から始めましょう。

String name = Optional.of("baeldung")
  .orElse(getRandomName());

注意してください getRandomName() ランダムを返すメソッドです名前からリスト名前:

public String getRandomName() {
    LOG.info("getRandomName() method - start");
    
    Random random = new Random();
    int index = random.nextInt(5);
    
    LOG.info("getRandomName() method - end");
    return names.get(index);
}

コードを実行すると、コンソールに次のメッセージが出力されます。

getRandomName() method - start
getRandomName() method - end

変数nameは、コード実行の最後に“ baeldung”を保持します。

これを使用すると、空でないオプションがある場合でも、orElse()のパラメーターが評価されていることを簡単に推測できます。

3.2. orElseGet()

次に、 orElseGet()を使用して同様のコードを記述してみましょう。

String name = Optional.of("baeldung")
  .orElseGet(() -> getRandomName());

上記のコードは、 getRandomName()メソッドを呼び出しません。

(Javadocから)引数として渡されたS サプライヤメソッドは、オプションの値が存在しない場合にのみ実行されることに注意してください。

したがって、この場合に orElseGet()を使用すると、ランダムなnameの計算にかかる時間を節約できます。

4. パフォーマンスへの影響の測定

ここで、パフォーマンスの違いも理解するために、 JMH を使用して、実際の数値を確認してみましょう。

@Benchmark
@BenchmarkMode(Mode.AverageTime)
public String orElseBenchmark() {
    return Optional.of("baeldung").orElse(getRandomName());
}

そしてorElseGet()

@Benchmark
@BenchmarkMode(Mode.AverageTime)
public String orElseGetBenchmark() {
    return Optional.of("baeldung").orElseGet(() -> getRandomName());
}

ベンチマークメソッドを実行すると、次のようになります。

Benchmark           Mode  Cnt      Score       Error  Units
orElseBenchmark     avgt   20  60934.425 ± 15115.599  ns/op
orElseGetBenchmark  avgt   20      3.798 ±     0.030  ns/op

ご覧のとおり、このような単純なユースケースのシナリオであっても、パフォーマンスへの影響はかなりのものになる可能性があります。

上記の数値は若干異なる場合があります。 ただし、 orElseGet()は、特定の例ではorElse()を明らかに上回っています。

結局のところ、 orElse()には、実行ごとの getRandomName()メソッドの計算が含まれます。

5. 重要なことは何ですか?

パフォーマンスの側面とは別に、検討する価値のある他の要因は次のとおりです。

  • メソッドが追加のロジックを実行する場合はどうなりますか? 例えば DBの挿入または更新を行う
  • orElse()パラメータにオブジェクトを割り当てても、理由もなく「その他」オブジェクトを作成しています
    String name = Optional.of("baeldung").orElse("Other")

そのため、ニーズに応じて、 orElse() orElseGet()の間で慎重に決定することが重要です。 デフォルトでは、デフォルトのオブジェクトがすでに構築されており、直接アクセスできる場合を除いて、毎回orElseGet()を使用する方が理にかなっています。

6. 結論

この記事では、オプションのorElse()メソッドと OrElseGet()メソッドの間の微妙な違いを学びました。 また、そのような単純な概念がどのように深い意味を持つことがあるかについても説明しました。

いつものように、完全なソースコードはGithubにあります。