What is the difference between the orelse() and orElseGet() methods of java.util.Optional?

Asked

Viewed 822 times

6

1 answer

6


Both return something if the Optional has no value.

The difference is in the orElse you provide the value to be returned, and orElseGet you provide a Supplier (an object that returns the value). Ex:

Optional<String> opt = Optional.empty();

System.out.println(opt.orElse("ola"));
System.out.println(opt.orElseGet(() -> "ola"));

Both print "ola". Of course within the orElseGet you can create a method as complex as you want:

System.out.println(opt.orElseGet(() -> {
    // faz outras coisas complexas aqui
    return resultadoDasCoisasComplexasAcima;
}));

But nothing prevents the method that does various complex things from being called directly and the result passed to orElse:

System.out.println(opt.orElse(metodoQueFazVariasCoisasComplexas()));

The difference is that in this case the method is called and its return is passed to orElse. Already if I call orElseGet, the method is only called if the Optional has no value:

public String metodo() {
    System.out.println("dentro do método");
    return "ola";
}
...

Optional<String> opt = Optional.empty();
System.out.println(opt.orElse(metodo()));
System.out.println(opt.orElseGet(() -> metodo()));

Like the Optional is empty, both will call by the method. The output is:

dentro do método
ola
dentro do método
ola

But if the Optional is not empty:

Optional<String> opt = Optional.of("teste");
System.out.println(opt.orElse(metodo()));
System.out.println(opt.orElseGet(() -> metodo()));

The method is only called in the first case, because the return of it must be passed to orElse. Already the orElseGet only calls the method if the Optional is empty (then in this case it is not called). The output is:

dentro do método
teste
teste

This makes a difference in cases where the method to be called is very expensive (it makes complex, time-consuming operations, spends a lot of processing or memory, the returned object is "very large", etc.). In such cases, use orElseGet is a better option than orElse, because then the method is only called when really necessary.

And as quoted in the comments, there is still the method orElseThrow, who receives a Supplier which creates an exception. In this case, the exception is cast if the Optional be empty:

Optional<String> opt = Optional.empty();
String valor = opt.orElseThrow(IllegalArgumentException::new);

In the code above, as the Optional is empty, a IllegalArgumentException.

  • I would put the real need case: when the default value is weighed to be generated. But how (apart from this detail) your answer would be the same as I would put, is the suggestion of improvement =)

  • Perhaps you could put as a curiosity the question of orElseThrow

  • 1

    @Jeffersonquesado Updated reply, thanks for the suggestions!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.