Optional.orElse()와 Optional.OrseGet()의 차이점
와 방법의 차이를 이해하려고 합니다.
의 orElse()
method는 "존재하면 값을 반환하고 그렇지 않으면 other를 반환한다"입니다.
「」, 「」의 .orElseGet()
method는 "있는 경우 값을 반환하고 그렇지 않은 경우 다른 값을 호출하고 해당 호출 결과를 반환합니다."입니다.
orElseGet()
으로 어떤 파라미터도 않고 기능 합니다.T
에서 '어느 정도'를 해야 합니까?orElseGet()
T myDefault()
optional.orElse(myDefault())
optional.orElseGet(() -> myDefault())
것 같다orElseGet()
(좀 더 안전한 더 이 될 했습니다.)Optional<T>
누구의.get()
않다NoSuchElementException
★★★★★★★★★★★★★★★★★」isPresent()
항상 true를 반환합니다...하지만 분명히 그렇지 않다.냥냥돌돌돌돌다다T
orElse()
를 참조해 주세요.
제가 놓치고 있는 다른 점이 있나요?
다음 두 가지 시나리오를 사용합니다.
Optional<Foo> opt = ...
Foo x = opt.orElse( new Foo() );
Foo y = opt.orElseGet( Foo::new );
ifopt
값을 포함하지 않습니다. 두 값은 실제로 동일합니다., 만약 ★★★★★★★★★★★★★★★★.opt
값이 포함되어 있습니다.Foo
브젝젝 츠요시
P.s.: 물론 이 예에서는 차이를 측정할 수 없을 것입니다만, 예를 들어 리모트 Web 서비스나 데이터베이스에서 기본값을 취득해야 하는 경우, 그 차이는 갑자기 매우 중요해집니다.
단답:
- 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 (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");
}
}
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()를 사용하세요.thus따는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);
orElse
apicall().value
이치노 의 는, 「」입니다.orElseGet
평가가 이루어지는 것은, 다음과 같은 경우 뿐입니다.oldValue
어어있있있있다다 orElseGet
느긋한 평가를 가능하게 합니다.
우선 두 방법의 선언을 확인합니다.
1) OrElse:논리를 실행하고 결과를 인수로 전달합니다.
public T orElse(T other) {
return value != null ? value : other;
}
2) OrElseGet: 옵션 내의 값이 null인 경우 로직을 실행합니다.
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
위 선언에 대한 설명:"Optional.orElse" 인수는 옵션의 오브젝트 값에 관계없이 항상 실행됩니다(null, empty 또는 value)."Optional.orElse"를 사용할 때는 항상 위의 사항을 고려하십시오. 그렇지 않으면 다음과 같은 상황에서 "Optional.orElse"를 사용하면 매우 위험할 수 있습니다.
위험-1) 로깅 문제:orElse 내의 콘텐츠에 로그문이 포함되어 있는 경우:이 경우 매번 로깅하게 됩니다.
Optional.of(getModel())
.map(x -> {
//some logic
})
.orElse(getDefaultAndLogError());
getDefaultAndLogError() {
log.error("No Data found, Returning default");
return defaultValue;
}
리스크-2) 퍼포먼스 문제:OrElse 내의 콘텐츠가 시간이 많이 걸리는 경우:시간이 많이 걸리는 콘텐츠는 임의의 I/O 운영 DB 호출, API 호출, 파일 읽기입니다.이러한 컨텐츠를 orElse()에 넣으면 시스템은 결국 쓸모없는 코드를 실행하게 됩니다.
Optional.of(getModel())
.map(x -> //some logic)
.orElse(getDefaultFromDb());
getDefaultFromDb() {
return dataBaseServe.getDefaultValue(); //api call, db call.
}
리스크-3) 부정한 상태 또는 버그 문제:OrElse 내의 콘텐츠가 일부 개체 상태를 변환하는 경우:Optional.map 함수 내에서 같은 오브젝트를 다른 장소에서 사용하고 있을 가능성이 있으며, 이로 인해 중대한 버그가 발생할 수 있습니다.
List<Model> list = new ArrayList<>();
Optional.of(getModel())
.map(x -> {
})
.orElse(get(list));
get(List < String > list) {
log.error("No Data found, Returning default");
list.add(defaultValue);
return defaultValue;
}
그럼 언제쯤 orElse()로 갈 수 있을까요?기본값이 상수 개체인 enum인 경우 orElse를 사용하는 것이 좋습니다.위의 경우 모두 Optional.orElse() 대신 Optional.orElseGet()(Optional에 빈 값이 포함되어 있을 때만 실행됨)을 사용할 수 있습니다.왜일까요?orElse에서는 기본 결과 값을 전달하지만 orElseGet에서는 공급업체를 전달하고 공급업체 메서드는 Optional 값이 null인 경우에만 실행됩니다.
여기서 얻을 수 있는 주요 포인트:
- 로그 문이 포함된 경우 "Optional.orElse"를 사용하지 마십시오.
- 시간이 많이 걸리는 논리가 포함된 경우 "Optional.orElse"를 사용하지 마십시오.
- 일부 오브젝트 상태를 변환하는 경우에는 "Optional.orElse"를 사용하지 마십시오.
- 정수 열거형을 반환해야 하는 경우 "Optional.orElse"를 사용합니다.
- 1, 2, 3번째 포인트에서 언급된 상황에서는 "Optional.OrseGet"을 선호합니다.
제 매체 블로그의 포인트 2("Optional.map/Optional.orElse")에서 설명했습니다.Java8을 코더가 아닌 프로그래머로 사용
그 차이는 매우 미묘하며, 만약 당신이 많은 주의를 기울이지 않는다면 당신은 그것을 잘못된 방법으로 계속 사용할 것입니다.
차이를 하는 가장 좋은 입니다.orElse()
★★★★★★★★★★★★★★★★★」orElseGet()
라는 것이다.orElse()
경우 됩니다.Optional<T>
무효인지 아닌지는 몰라도orElseGet()
은 하다Optional<T>
null 입니다.
orElse의 사전적 의미는 :- 무엇인가가 존재하지 않을 때 파트를 실행하지만, 여기서 모순됩니다.다음 예를 참조하십시오.
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";
}
출력: non Empty Option이 NULL이 아닙니다.아직 실행 중입니다.
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";
}
출력: empty 옵션은 NULL입니다.실행 중입니다.사전에 따르면 정상입니다.
★★★의
orElseGet()
이 방법은 사전적 의미에 따라 진행됩니다.orElseGet()
Optional이 null인 경우에만 부품이 실행됩니다.
벤치마크:
+--------------------+------+-----+------------+-------------+-------+
| 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()
이치노
기본적인 예를 원하는 저와 같은 사람들의 의심이 해소되기를 바랍니다.
다음 예시는 그 차이를 보여 줍니다.
String destroyTheWorld() {
// destroy the world logic
return "successfully destroyed the world";
}
Optional<String> opt = Optional.of("Save the world");
// we're dead
opt.orElse(destroyTheWorld());
// we're safe
opt.orElseGet(() -> destroyTheWorld());
정답은 문서에도 표시됩니다.
다음과 같습니다public T orElseGet(Supplier<? extends T> other)
.
값이 있으면 값을 반환하고, 없으면 다른 값을 호출하여 해당 호출 결과를 반환합니다.
Supplier
이 경우 호출되지 않습니다.Optional
반면,, whereas whereas,, whereas whereas,.
다음과 같습니다public T orElse(T other)
.
값이 있으면 값을 반환하고 없으면 다른 값을 반환합니다.
ifother
이 메서드는되지만, 이 이 메서드는 호출되지만 값이 반환되지 않습니다.Optional
재한한다
다음 코드를 고려합니다.
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();
}
}
가 얻는다면value
Optional.<String>ofNullable(null)
의 orElseGet()을 orElse()가 됩니다value
Optional.<String>ofNullable("test")
,orelesMethod()
orElseGet()
불리 will will will will will will will will will will will will will will will will will 。orElse()
불릴 예요.
둘 다 하나의 옵션 기본값을 반환하는 데 사용되지만 dafault 값을 생성하기 위해 메서드를 사용하는 경우:
- orElse: Optional이 비어 있지 않은 경우에도 항상 메서드를 실행합니다.
- orElseGet: 옵션(+ 퍼포먼스!)이 비어 있는 경우에만 실행됩니다.
다음 예(클래스 Optional Example)를 참조하십시오.
public static void main(String[] args) {
Optional<String> optionalNotEmpty = Optional.of("StringVal");
// orElse: getDefaultValue called (useless)
System.out.println(optionalNotEmpty.orElse(getDefaultValue()));
// orElseGet: getDefaultValue not called (better solution)
System.out.println(optionalNotEmpty.orElseGet(OptionalExample::getDefaultValue));
}
public static String getDefaultValue() {
System.out.println("called");
return "default value";
}
출력:
called
StringVal
StringVal
언급URL : https://stackoverflow.com/questions/33170109/difference-between-optional-orelse-and-optional-orelseget
'programing' 카테고리의 다른 글
String에 있는 Java의 hashCode()는 왜 31을 승수로 사용합니까? (0) | 2022.07.04 |
---|---|
Http Servlet Request - 참조 URL을 얻는 방법 (0) | 2022.07.04 |
vue-cli3을 사용하여 플러그인 제거 (0) | 2022.07.04 |
Guice 바인딩 덮어쓰기 (0) | 2022.07.04 |
Eslint 상태가 이미 선언된 [Vuex] (0) | 2022.07.04 |