Programing

`Optional.orElse ()`와`Optional.orElseGet ()`의 차이점

lottogame 2020. 5. 19. 08:03
반응형

`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하지 NoSuchElementExceptionisPresent()항상 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가장 큰 차이점을 말할 것 입니다.orElseGetelse

이 간단한 예를 고려하십시오-

// 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, The orElseGet() 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 outperformed orElse() 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,

public T orElse(T other):

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

참고URL : https://stackoverflow.com/questions/33170109/difference-between-optional-orelse-and-optional-orelseget

반응형