Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When I need to use Optional.orElseGet() over Optional.orElse()

I need a clear explanation of this, even though I read this link on differences but no clear clarity. So can anyone explain to me on this in short with code?

like image 944
TVK Avatar asked May 30 '17 11:05

TVK


People also ask

What is difference between orElse and orElseGet?

orElse(): returns the value if present, otherwise returns other. orElseGet(): returns the value if present, otherwise invokes other and returns the result of its invocation.

How do you use orElse Optional?

The orElse() method of java. util. Optional class in Java is used to get the value of this Optional instance, if present. If there is no value present in this Optional instance, then this method returns the specified value.

What exception is thrown by Optional get () when not nested within Optional isPresent?

NoSuchElementException Exception Via orElseThrow() Since Java 10. Using the Optional. orElseThrow() method represents another elegant alternative to the isPresent()-get() pair. Sometimes, when an Optional value is not present, all you want to do is to throw a java.

What is the use of Optional ()?

Optional object is used to represent null with absent value. This class has various utility methods to facilitate code to handle values as 'available' or 'not available' instead of checking null values. It is introduced in Java 8 and is similar to what Optional is in Guava.


2 Answers

I think I am starting to understand your question. Execution order with Optional can be different from what we are used to in procedural programming (the same is true for Java streams and other code using lambdas).

I will use the two examples from Eugene’s answer:

    o1.orElse(new MyObject()); // 1055e4af 

This is plain old Java: it’s a call to orElse() taking new MyObject() as argument. So the argument is evaluated first and a new MyObject created. This is then passed to orElse(). orElse() looks to see whether a value is present in the Optional; if so it returns that value (discarding the newly created object); if not, it returns the object given to it in the argument. This was the simpler example.

    o1.orElseGet(() -> {
        System.out.println("Should I see this");
        return new MyObject();
    });

Again we have a method call with one argument, and again the argument is evaluated first. The lambda is only created and passed as a supplier. The code inside { } is not executed yet (you also see no Should I see this in Eugene’s output). Again orElseGet looks to see if there is a value present in the Optional. If there is, the value is returned and the supplier we passed is ignored. If there isn’t, the supplier is invoked, the code inside { } is executed to get the value to be returned from orElseGet().

In the first case, one may say that a MyObject is created and wasted. In the second a Supplier is created and wasted. What you get in return is terse and null-pointer safe code in both cases. So very often it’s not important which one you pick. If creating the MyObject is costly or has unwanted side effects, you will of course want the second version where the object is only created when it is asked for, and is never wasted. Eugene in a comment mentions the case where the returned object comes from a database call. Database calls are usually time-consuming enough that you don’t want to make one for no purpose.

like image 158
Ole V.V. Avatar answered Oct 19 '22 03:10

Ole V.V.


How about an example:

static class MyObject {
    public MyObject() {
        System.out.println("Creating one..." + this);
    }
}

And some usage:

  Optional<MyObject> o1 = Optional.of(new MyObject()); // 7382f612

    o1.orElse(new MyObject()); // 1055e4af 
    o1.orElseGet(() -> {
        System.out.println("Should I see this");
        return new MyObject();
    });

And some output:

 Creating one... MyObject@7382f612
 Creating one... MyObject@1055e4af

In case Optional has a value; orElse is still called but not used. On the contradictory orElseGet is not called.

Consider the case when creating the object is expensive; which one you will use?

It's actually easier to understand I think if you look in the code:

public T orElseGet(Supplier<? extends T> supplier) {
    return value != null ? value : supplier.get();
}
like image 44
Eugene Avatar answered Oct 19 '22 03:10

Eugene