본문 바로가기
학습/Java

orElse() vs orElseGet()

코동이 2021. 2. 18.

Optional에서 추가적인 행동을 위해서 사용하는 orElse()와 orElseGet()은 굉장히 비슷한 모양과 역할을 하고 있습니다. 하지만 모든 문서에서는 두개의 메서드에 대한 차이점을 강조하면서 유의하라고 설명합니다. 그래서 어떤 점이 다른지 좀 더 자세히 살펴보고자 합니다.

Oracle documentation(Optional)

위 사진의 오라클 문서에 따르면, 값이 존재한다면 값을 그대로 리턴하고 그렇지 않다면 other을 리턴한다고 나와있습니다. 단지 orElseGet()은 Supplier를 매개변수로 가지기 때문에 other을 호출하고 그 결과값을 리턴합니다. 이렇게 보면 크게 차이점이 없는 것이 실제로 맞고 비슷한 기능을 하고 있습니다. 하지만 아래의 예를 통해 차이점을 확인하겠습니다.

 

Optional 내에 null을 가진 경우

String text = null;
String defaultText = Optional.ofNullable(text).orElseGet(this::getDefaultValue);

defaultText = Optional.ofNullable(text).orElse(getDefaultValue());

public String getDefaultValue() {
	System.out.println("Getting Default Value");
    return "Default Value";
}

위의 예에서 defaultText는 Optional 객체 안에 null을 가진 text를 래핑합니다. 우리는 orElse()와 orElseGet() 2가지 접근법을 모두 사용하여 래핑된 값을 얻으려고 시도하고 합니다. 이 방법의 결과는 아래와 같습니다.

Getting default value...
Getting default value...

getDefaultValue 메서드가 각각의 경우에 호출되었습니다.

래핑된 값이 존재하지 않을 때, orElse()와 orElseGet()는 정확하게 같은 방식으로 작동합니다.

따라서 각각 getDefaultValue()가 실행되었고 출력문에 2개의 값이 찍혀있습니다.

 

Optional 내에 실제 값을 가진 경우

 

이제 text를 null 이 아닌 "default" 값을 할당하고 다시 실행해보겠습니다.

String text = "default";
String defaultText = Optional.ofNullable(text).orElseGet(this::getDefaultValue);

defaultText = Optional.ofNullable(text).orElse(getDefaultValue());

public String getDefaultValue() {
	System.out.println("Getting Default Value");
    return "Default Value";
}

 

Getting default value...

래핑된 값이 존재할 때, 이상적으로 orElse()와 orElseGet() 모두 getDefaultValue 메서드는 호출되서는 안됩니다:

하지만 값이 존재함에도 불구하고 orElse() 메서드가 호출됩니다. 즉, orElse() 메서드는 Optional<T>가 null이던지, 아닌지 고려하지 않고 항상 실행됩니다. 그러나 orElseGet() 메서드는 Optional<T>가 null일 때만 실행됩니다. 따라서, 출력문이 생성되었습니다.

 

이 예제에서는, JVM이 이미 어떻게 처리해야 하는지 사전 정보가 있기 때문에, orElse() 메서드가 실행되고 객체가 생성되는 비용이 크지 않습니다. 하지만 orElse() 메서드가 웹 서비스 혹은 DB 쿼리를 호출해야 한다면, 비용은 매우 비싸지게 될 것입니다.

 

 

위의 예제와 비슷하게 문자열을 리턴하는 메서드를 매개변수로 가진 경우 다음과 같은 Benchmark 결과를 냈습니다.

orElse() vs orElseGet()

 

결론

orElseGet() 메서드는 위와 특정 예제에서 orElse()의 성능을 압도적으로 뛰어넘습니다. orElse()를 사용한다면, 최대한 연산 비용이 적은 방법을 고민해야 합니다.

 

참조

dzone.com/articles/optionalorelse-vs-optionalorelseget

dzone.com/articles/java-8-optional-usage-and-best-practices

반응형