11

I've read the answers to this question about the difference between Optional.orElse() and Optional.orElseGet().

It seems that orElseGet() is always more efficient than orElse() because of lazy evaluation, and it's apparently visible even when benchmarking very simple examples like this one (see part 4): https://www.baeldung.com/java-optional-or-else-vs-or-else-get

So, are there any use cases where it's better to use orElse rather than orElseGet?

ZhaoGang
  • 4,491
  • 1
  • 27
  • 39
Retropiaf
  • 219
  • 3
  • 8
  • maybe if the chances that the Optional is empty is higher. – jcal Jan 09 '19 at 02:19
  • 3
    Like the link says: _"by default, it makes more sense to use orElseGet() every time **unless the default object is already constructed and accessible directly.**"_ – Jorn Vernee Jan 09 '19 at 02:20
  • It makes sense when you've already endured the cost of creating an object. Otherwise, you can delay object creation until it's actually required. – John Jan 09 '19 at 02:21

3 Answers3

12
  1. In most cases, you type less when using orElse, since it is shorter than orElseGet and, compare the signatures of them:

orElse(T other)
orElseGet(Supplier<? extends T> other)

a Supplier<? extends T> other is most likely longer than T other. If the performance is not so critical you may choose to type less. Programmer's effort also counts :-) For example, compare:

orElseGet(() -> 1)
orElse(1)
  1. As your link has mentioned:

by default, it makes more sense to use orElseGet() every time unless the default object is already constructed and accessible directly.

ZhaoGang
  • 4,491
  • 1
  • 27
  • 39
  • The first part doesn't really answer the question, other than to say "it's less verbose", which isn't a great reason. The 2nd part is the key. – Ted M. Young Dec 25 '21 at 20:56
3

One of the major use cases where it could be preferable would be when you know you need to fall back to a constant (or even an object already created) to default to. I mean, just compare how poor could this be :

int first = Stream.of(1,3,5).filter(i->i%2==0).findFirst().orElseGet(new Supplier<Integer>() {
    @Override
    public Integer get() {
        return 1;
    }
});

or its lambda representation

int first = Stream.of(1,3,5).filter(i->i%2==0).findFirst().orElseGet(() -> 1);

which is redundant as compared to

int first = Stream.of(1,3,5).filter(i->i%2==0).findFirst().orElse(1);
Naman
  • 27,789
  • 26
  • 218
  • 353
  • 2
    The first sentence is the key to the right answer for the actual question of "when to use" it (I think the lambda stuff gets in the way). If you have a constant or already-created object that you want to use when the optional is empty, then the .orElse() is the right way to go. – Ted M. Young Dec 25 '21 at 20:52
2

Below is the short answer, for a more detailed answer, please check out my stackoverflow answer here

  • orElse() will always call the given function whether you want it or not, regardless of Optional.isPresent() value
  • orElseGet() will only call the given function when the Optional.isPresent() == false

And as the first approach will always get the resource, you might want to consider the second approach when the required resource is expensive to get.

Hoa Nguyen
  • 13,452
  • 11
  • 45
  • 44