`Optional.orElse ()`와`Optional.orElseGet ()`의 차이점
Optional<T>.orElse()
와 Optional<T>.orElseGet()
방법 의 차이점을 이해하려고 합니다.
이 orElse()
방법에 대한 설명 은 "있는 경우 값을 반환하고, 그렇지 않으면 다른 값을 반환합니다."입니다.
그 orElseGet()
방법에 대한 설명 은 "있는 경우 값을 반환하고, 그렇지 않으면 다른 것을 호출하고 해당 호출의 결과를 반환합니다."입니다.
이 orElseGet()
메소드는 기본적으로 매개 변수를 취하지 않고을 리턴하는 공급 업체 기능 인터페이스를 사용합니다 T
.
어떤 상황에서 사용해야 orElseGet()
합니까? 당신이 방법을 가지고 있다면 T myDefault()
왜 optional.orElse(myDefault())
오히려 하지 optional.orElseGet(() -> myDefault())
않겠습니까?
orElseGet()
람다 식의 실행을 나중에 또는 다른 것으로 연기하는 것 같지 않으므로 요점은 무엇입니까? (나는 그것이 안전한 반환 경우가 더 유용 할 것이라고 생각했을 Optional<T>
그 get()
를 throw하지 NoSuchElementException
및 isPresent()
항상 true를 반환 ...하지만 분명이 아니, 그것은 단지 반환 T
처럼 orElse()
).
내가 놓친 다른 차이점이 있습니까?
다음 두 가지 시나리오를 수행하십시오.
Optional<Foo> opt = ...
Foo x = opt.orElse( new Foo() );
Foo y = opt.orElseGet( Foo::new );
경우 opt
값을 포함하지 않는, 두 사람은 참으로 동일합니다. 하지만 opt
않는 값을 포함, 얼마나 많은 Foo
객체를 생성 할 것인가?
추신 : 물론이 예에서는 차이를 측정 할 수는 없지만 원격 웹 서비스 또는 데이터베이스에서 기본값을 가져와야하는 경우 갑자기 매우 중요합니다.
짧은 답변:
- orElse () 는
Optional.isPresent()
값에 관계없이 원하는지 여부에 관계없이 항상 주어진 함수를 호출합니다. - orElseGet () 은 주어진 함수 만 호출 할 때
Optional.isPresent() == false
실제 코드에서 필요한 리소스 를 얻는 데 비용 이 많이 드는 경우 두 번째 방법을 고려할 수 있습니다.
// 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
, 두 가지 방법 사이에 차이가 없습니다. 그러나, optional.isPresent() == true
, orElse()
항상 당신이 원하는 여부 후속 함수를 호출합니다.
마지막으로 사용 된 테스트 케이스는 다음과 같습니다.
결과:
------------- Scenario 1 - orElse() --------------------
1.1. Optional.isPresent() == true
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");
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");
}
}
Kudo가 언급 한 문제에 대해 여기에 도달했습니다 .
나는 다른 사람들을 위해 내 경험을 공유하고 있습니다.
orElse
또는 orElseGet
질문입니다.
static String B() {
System.out.println("B()...");
return "B";
}
public static void main(final String... args) {
System.out.println(Optional.of("A").orElse(B()));
System.out.println(Optional.of("A").orElseGet(() -> B()));
}
인쇄물
B()...
A
A
orElse
선택적 값과 상호 의존적으로 B () 값을 평가합니다. 따라서 orElseGet
게으르다.
조건 에서 새로운 가치를 얻기 위해 무언가를 평가하고 싶을 때 orElse
와 가장 큰 차이점을 말할 것 입니다.orElseGet
else
이 간단한 예를 고려하십시오-
// oldValue is String type field that can be NULL
String value;
if (oldValue != null) {
value = oldValue;
} else {
value = apicall().value;
}
이제 위 예제 Optional
를와 함께 사용하도록 변환 해 보겠습니다 orElse
.
// oldValue is Optional type field
String value = oldValue.orElse(apicall().value);
이제 위 예제 Optional
를와 함께 사용하도록 변환 해 보겠습니다 orElseGet
.
// oldValue is Optional type field
String value = oldValue.orElseGet(() -> apicall().value);
When orElse
is invoked, the apicall().value
is evaluated and passed to the method. Whereas, in the case of orElseGet
the evaluation only happens if the oldValue
is empty. orElseGet
allows lazy evaluation.
The difference is pretty subtle and if you dont pay much attention then you will keep it using in a wrong way.
Best way to understand the difference between orElse()
and orElseGet()
is that orElse()
will always be executed if the Optional<T>
is null or not, But orElseGet()
will only be executed when Optional<T>
is null.
The dictionary meaning of orElse is :- execute the part when something is not present, but here it contradicts, see the below example:
Optional<String> nonEmptyOptional = Optional.of("Vishwa Ratna");
String value = nonEmptyOptional.orElse(iAmStillExecuted());
public static String iAmStillExecuted(){
System.out.println("nonEmptyOptional is not NULL,still I am being executed");
return "I got executed";
}
Output: nonEmptyOptional is not NULL,still I am being executed
Optional<String> emptyOptional = Optional.ofNullable(null);
String value = emptyOptional.orElse(iAmStillExecuted());
public static String iAmStillExecuted(){
System.out.println("emptyOptional is NULL, I am being executed, it is normal as
per dictionary");
return "I got executed";
}
Output: emptyOptional is NULL, I am being executed, it is normal as per dictionary
For
orElseGet()
, The method goes as per dictionary meaning, TheorElseGet()
part will be executed only when the Optional is null.
Benchmarks:
+--------------------+------+-----+------------+-------------+-------+
| Benchmark | Mode | Cnt | Score | Error | Units |
+--------------------+------+-----+------------+-------------+-------+
| orElseBenchmark | avgt | 20 | 60934.425 | ± 15115.599 | ns/op |
+--------------------+------+-----+------------+-------------+-------+
| orElseGetBenchmark | avgt | 20 | 3.798 | ± 0.030 | ns/op |
+--------------------+------+-----+------------+-------------+-------+
Remarks:
orElseGet()
has clearly outperformedorElse()
for our particular example.
Hope it clears the doubts of people like me who wants the very basic ground example :)
The following example should demonstrate the difference:
String destroyTheWorld() {
// destroy the world logic
return "successfully destroyed the world";
}
Optional<String> opt = Optional.empty();
// we're dead
opt.orElse(destroyTheWorld());
// we're safe
opt.orElseGet(() -> destroyTheWorld());
The answer appears in the docs as well.
public T orElseGet(Supplier<? extends T> other)
:
Return the value if present, otherwise invoke other and return the result of that invocation.
The Supplier
won't be invoked if the Optional
presents. whereas,
Return the value if present, otherwise return other.
If other
is a method that returns a string, it will be invoked, but it's value won't be returned in case the Optional
exists.
Considering the following code:
import java.util.Optional;
// one class needs to have a main() method
public class Test
{
public String orelesMethod() {
System.out.println("in the Method");
return "hello";
}
public void test() {
String value;
value = Optional.<String>ofNullable("test").orElseGet(this::orelesMethod);
System.out.println(value);
value = Optional.<String>ofNullable("test").orElse(orelesMethod());
System.out.println(value);
}
// arguments are passed using the text field below this editor
public static void main(String[] args)
{
Test test = new Test();
test.test();
}
}
if we get value
in this way: Optional.<String>ofNullable(null)
, there is no difference between orElseGet() and orElse(), but if we get value
in this way: Optional.<String>ofNullable("test")
, orelesMethod()
in orElseGet()
will not be called but in orElse()
it will be called
'Programing' 카테고리의 다른 글
Visual Studio Code에서 닫는 대괄호로 이동 (0) | 2020.05.19 |
---|---|
ModelState.AddModelError-속성이 아닌 오류를 어떻게 추가합니까? (0) | 2020.05.19 |
반응 성분을 다른 반응 성분으로 전달하여 첫 번째 성분의 내용을 포함시키는 방법은 무엇입니까? (0) | 2020.05.19 |
Tornado 사용시기, Twisted / Cyclone / GEvent / 기타 사용시기 (0) | 2020.05.19 |
Perl에서 나와 우리의 차이점은 무엇입니까? (0) | 2020.05.19 |