Difference between Optional.orElse() and Optional.orElseGet()
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Optional.orElse(...) and Optional.orElseGet(...) both provide fallback values, but they do not behave the same way. The real difference is when the fallback expression is evaluated: orElse is eager, while orElseGet is lazy.
orElse Evaluates the Default Immediately
orElse takes an actual value, not a supplier. That means the fallback expression is evaluated before the method call, even if the Optional already contains a value.
In this example, expensiveDefault() still runs, even though the optional already contains "Ana".
That is the key behavior to remember.
orElseGet Computes the Default Only If Needed
orElseGet takes a Supplier, so the fallback code runs only when the optional is empty.
Here, the supplier is not invoked because the optional already has a value.
This makes orElseGet the better choice when computing the fallback is expensive, has side effects, or should happen only when truly necessary.
Use Cases for Each One
A practical rule is:
- use
orElsewhen the fallback is already cheap and available - use
orElseGetwhen the fallback requires work to compute
For example, a literal string or constant object is a fine fit for orElse.
But a database lookup, log message, or object construction with real cost is a better fit for orElseGet.
Side Effects Matter Too
The performance difference is often discussed first, but side effects are just as important. If the fallback method writes logs, increments counters, or calls external services, using orElse may trigger those effects even when the optional is present.
That can create confusing behavior that looks like a logic bug rather than a performance bug.
So the real question is not only "is the fallback expensive" but also "should this fallback code run at all unless the optional is empty."
A Small Demonstration
Only the second line invokes the supplier. That is the lazy behavior orElseGet is designed for.
A good way to think about the choice is that orElse is for a fallback value you already have, while orElseGet is for a fallback value you may have to compute. That framing is often easier to remember than the eager-versus-lazy terminology alone.
This distinction becomes especially visible when the fallback creates objects, calls services, or logs diagnostic data. In those cases, orElseGet is not just a micro-optimization; it preserves the meaning that fallback work should happen only when the optional is actually empty.
Reading the call site out loud can help: if the fallback feels like an action rather than a literal value, orElseGet is usually the more intention-revealing choice.
Common Pitfalls
Using orElse(expensiveCall()) and expecting the expensive call not to run is the classic mistake.
Choosing orElseGet for a trivial constant is not wrong, but it is often unnecessary ceremony.
Ignoring fallback side effects can make orElse produce surprising behavior even when the optional is present.
Summary
- '
orElseevaluates its fallback eagerly.' - '
orElseGetevaluates its fallback lazily through a supplier.' - Use
orElsefor cheap already-available defaults. - Use
orElseGetwhen the fallback is expensive or should only run when needed.

