First of all check the declaration of both the methods.
1) OrElse: Execute logic and pass result as argument.
public T orElse(T other) {
return value != null ? value : other;
}
2) OrElseGet: Execute logic if value inside the optional is null
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
Some explanation on above declaration:
The argument of “Optional.orElse” always gets executed irrespective of the value of the object in optional (null, empty or with value). Always consider the above-mentioned point in mind while using “Optional.orElse”, otherwise use of “Optional.orElse” can be very risky in the following situation.
Risk-1) Logging Issue: If content inside orElse contains any log statement:
In this case, you will end up logging it every time.
Optional.of(getModel())
.map(x -> {
//some logic
})
.orElse(getDefaultAndLogError());
getDefaultAndLogError() {
log.error("No Data found, Returning default");
return defaultValue;
}
Risk-2) Performance Issue: If content inside orElse is time-intensive:
Time intensive content can be any i/o operations DB call, API call, file reading. If we put such content in orElse(), the system will end up executing a code of no use.
Optional.of(getModel())
.map(x -> //some logic)
.orElse(getDefaultFromDb());
getDefaultFromDb() {
return dataBaseServe.getDefaultValue(); //api call, db call.
}
Risk-3) Illegal State or Bug Issue: If content inside orElse is mutating some object state:
We might be using the same object at another place let say inside Optional.map function and it can put us in a critical bug.
List<Model> list = new ArrayList<>();
Optional.of(getModel())
.map(x -> {
})
.orElse(get(list));
get(List < String > list) {
log.error("No Data found, Returning default");
list.add(defaultValue);
return defaultValue;
}
Then, When can we go with orElse()?
Prefer using orElse when the default value is some constant object, enum. In all above cases we can go with Optional.orElseGet() (which only executes when Optional contains empty value)instead of Optional.orElse(). Why?? In orElse, we pass default result value, but in orElseGet we pass Supplier and method of Supplier only executes if the value in Optional is null.
Key takeaways from this:
- Do not use “Optional.orElse” if it contains any log statement.
- Do not use “Optional.orElse” if it contains time-intensive logic.
- Do not use “Optional.orElse” if it is mutating some object state.
- Use “Optional.orElse” if we have to return a constant, enum.
- Prefer “Optional.orElseGet” in the situations mentioned in 1,2 and 3rd points.
I have explained this in point-2 (“Optional.map/Optional.orElse” != “if/else”) my medium blog. Use Java8 as a programmer not as a coder
orElseGet
it calls supplier only if value is absent. – PaloczorElse()
themyDefault()
method is still called, but its return value is just not used. – AnabiosisorElseGet()
can result in some serious bugs: medium.com/alphadev-thoughts/… – Caldwell