Back to Blog
Java

Java Optional orElse vs orElseGet

java optional orelse vs orelseget: Understand the difference between Java Optional orElse and orElseGet, including eager vs lazy evaluation and when to use each fallba...

Java OptionalorElseorElseGetLazy EvaluationNull Handling
Diagram comparing Java Optional orElse and orElseGet evaluation timing

When you work with Optional in Java, you often need to provide a fallback value for the empty case. The two methods orElse and orElseGet look similar, but they behave differently in an important way. This article explains java optional orelse vs orelseget and helps you decide which one fits your situation.

How orElse Works

The orElse method takes a value and returns it if the Optional is empty. The argument is evaluated eagerly, meaning it is computed before the method is even called. Consider this example:

Optional<String> name = Optional.empty(); String result = name.orElse("default");

Here, the string "default" is created at the point where the argument is passed, regardless of whether the Optional is empty. If the fallback expression is a method call, that method runs immediately, even when the Optional contains a value.

How orElseGet Works

orElseGet takes a Supplier<T> and invokes it only when the Optional is empty. The supplier is evaluated lazily. The same example with orElseGet looks like this:

Optional<String> name = Optional.empty(); String result = name.orElseGet(() -> "default");

The lambda is not executed unless the Optional is empty. If the Optional already contains a value, the supplier is never called.

The Key Difference: Evaluation Timing

The fundamental difference is when the fallback is evaluated. orElse always evaluates its argument, even if the Optional is non-empty. orElseGet defers evaluation until it is actually needed. This matters when the fallback is expensive to compute, has side effects, or depends on external state that might change.

Consider a method that fetches a default configuration from a remote service:

public String getConfig(Optional<String> config) { return config.orElse(fetchDefaultConfig()); } public String getConfigLazy(Optional<String> config) { return config.orElseGet(() -> fetchDefaultConfig()); }

In the first version, fetchDefaultConfig() is called every time getConfig is invoked, even if config already holds a value. In the second version, the call only happens when config is empty.

When to Use orElse

Use orElse when the fallback is a constant, a simple literal, or a value that is already computed and cheap to obtain. There is no downside to eager evaluation in those cases. For example:

String result = optionalValue.orElse("unknown");

If the fallback is a static constant or a field that is already initialized, orElse is clear and concise.

When to Use orElseGet

Use orElseGet when the fallback involves computation, method calls, object creation, or any operation that could have side effects. This includes scenarios where you want to avoid unnecessary work when the Optional is present. A common pattern is building a default object:

Optional<Order> order = findOrder(id); Order result = order.orElseGet(() -> createDefaultOrder());

Here, createDefaultOrder() is only invoked when no order is found. This can save significant resources if the default is complex to construct.

Performance and Side Effects

The performance impact of choosing one over the other depends on the cost of the fallback expression. If the fallback is trivial, the difference is negligible. But if the fallback involves database queries, network calls, or heavy computation, using orElse can cause unnecessary work. There is also a correctness concern: if the fallback has side effects, such as logging or modifying state, orElse will trigger those side effects even when the Optional is non-empty. orElseGet avoids that because the supplier is never invoked in that case.

Common Pitfalls and Best Practices

A common mistake is assuming that orElse is lazy. It is not. Another mistake is using orElseGet with a constant when a simple orElse would be more readable. There is no performance penalty for using orElse with a constant, but using orElseGet with a lambda that just returns a constant adds unnecessary ceremony.

When the fallback is a method reference that already returns the desired type, orElseGet is a natural fit:

String result = optional.orElseGet(this::defaultValue);

If the fallback requires no parameters and is cheap, orElse is simpler. The decision should be based on the cost and side effects of the fallback expression, not on a fixed rule.

java optional orelse vs orelseget: Practical Usage and Code | RYUSLOG DEV