Java
Optional.orElse()
Optional.orElseGet()
Programming Concepts
Code Comparison

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.

java
1import java.util.Optional;
2
3String name = Optional.of("Ana").orElse(expensiveDefault());
4
5static String expensiveDefault() {
6    System.out.println("building default");
7    return "fallback";
8}

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.

java
1import java.util.Optional;
2
3String name = Optional.of("Ana").orElseGet(() -> expensiveDefault());
4
5static String expensiveDefault() {
6    System.out.println("building default");
7    return "fallback";
8}

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 orElse when the fallback is already cheap and available
  • use orElseGet when the fallback requires work to compute

For example, a literal string or constant object is a fine fit for orElse.

java
String status = maybeStatus.orElse("unknown");

But a database lookup, log message, or object construction with real cost is a better fit for orElseGet.

java
User user = maybeUser.orElseGet(() -> loadDefaultUser());

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

java
1Optional<String> present = Optional.of("real");
2Optional<String> empty = Optional.empty();
3
4System.out.println(present.orElseGet(() -> expensiveDefault()));
5System.out.println(empty.orElseGet(() -> expensiveDefault()));

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

  • 'orElse evaluates its fallback eagerly.'
  • 'orElseGet evaluates its fallback lazily through a supplier.'
  • Use orElse for cheap already-available defaults.
  • Use orElseGet when the fallback is expensive or should only run when needed.

Course illustration
Course illustration

All Rights Reserved.