The main difference between orElse and orElseGet in the Java Optional class is when and how the default value is computed:
- orElse(T other): The argument is always evaluated, even if the Optional already has a value.
- orElseGet(Supplier<? extends T> otherSupplier): The supplier is only called if the Optional is empty, meaning the logic to create the default value is evaluated lazily, only when needed
Method | Argument Type | When is it evaluated? | Use Case |
orElse | T (actual value/result) | Always, even if Optional is present | Use when default value is cheap to create or constant |
orElseGet | Supplier<? extends T> | Only if Optional is empty | Use when creation of default is expensive or involves logic |
Example
Optional<String> opt = Optional.of("present"); // orElse: computes getDefaultValue() even though not used opt.orElse(getDefaultValue()); // orElseGet: only computes getDefaultValue() if Optional is empty opt.orElseGet(() -> getDefaultValue());
If getDefaultValue()
prints something, with orElse()
you’ll see the print statement executed every time, even when the Optional’s value is present. With orElseGet()
, it will only execute if the Optional is empty.
Performance and Best Practices
- Use orElse when the default value is simple or constant (e.g., a literal).
- Use orElseGet when the default value computation is expensive (e.g., database call, heavy calculation), or has side effects, because it avoids unnecessary work.
In summary, prefer orElseGet for lazy/economical computation of fallbacks, orElse for cheap constants. Using orElse with expensive or side-effecting defaults can negatively impact your app’s performance or behavior