私は、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()
返されるだけです)。T
orElse()
私が見逃している他の違いはありますか?
ベストアンサー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() == true
、orElse()
必要かどうかに関係なく、常に後続の関数が呼び出されます。
最後に、使用したテストケースは以下のとおりです。
結果:
------------- 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");
}
}