Java 8 Optional is used to represent Optional object or empty value instead null reference. This will help to avoid null pointer exception which occurs when we try to perform some operation on null reference object. For accessing the value from optional object, there are few methods like get(), orELse(), orElseGet(), etc. Whenever we look at orElse vs orElseGet() method, we always get confused. What is the difference and when to use which method?
When we overview these methods, we think that we can use orElse(functionCall()) instead of orElseGet(Class::functionDef), and it will have the same outcome. Then why is there a need to create two different methods?
The straight answer is there is difference in the behaviors and they make huge difference in case of performance, for instance orElse() method returns value and orElseGet() method calls the function.
Let us see each of their behavior in detail in this blog.
Syntax of orElse vs orElseGet
OrElse() method takes a parameter which will be returned if the optional doesn’t have value.
OrElseGet() method needs a function which will be executed to return value if the optional doesn’t have value.
This shows that orElse method needs a value and orElseGet method needs supplier functions.
If we pass function to orElse method it will always be executed to fit the syntax before executing the statement. However, in case of orElseGet method we cannot pass value and the function is executed only if optional doesn’t have value.
Difference: orElse vs orElseGet
We will use following function to get value if optional is null
public String getFunctionForTest() {
System.out.println("\n ===== function called ===== ");
return "default value";
}
Let's take scenario of Optional object has null value
public void orElseVSorElseGet() {
Optional<String> optional = Optional.ofNullable(null);
String orElseGetResult = optional.orElseGet( this::getFunctionForTest);
System.out.println("value in orElseGetResult " + orElseGetResult);
String orElseResult = optional.orElse(this.getFunctionForTest());
System.out.println("value in orElseResult " + orElseResult);
}
Output:
===== function called =====
value in orElseGetResult default value
===== function called =====
value in orElseResult default value
As we can see that the option doesn’t have value and we need to take value form else part. So as expected, the function is called in both cases.
Now let's take an example where we have the value in optional object and we don’t need to execute else part
public void orElseVSorElseGet() {
Optional<String> optional = Optional.ofNullable("value found");
String orElseGetResult = optional.orElseGet(this::getFunctionForTest);
System.out.println("value in orElseGetResult " + orElseGetResult);
String orElseResult = optional.orElse(this.getFunctionForTest());
System.out.println("value in orElseResult " + orElseResult);
}
Output:
value in orElseGetResult default value
===== function called =====
value in orElseResult default value
As we know that the option object has a value, so we don’t need to take value form else part.
So we expect that function should not be executed. However the function was executed in the case of orElse method.
In the above example we may not notice the performance difference, but when we have complex process to take default value it affects performance. You can consider the example where you need database or network call to take default values it will be slower even if you have value.
In such cases it's better to use orElseGet method.
In case of orElse, else part is computed even if value is present. If we have default static value then orElse is good choice. If you need a computation logic for default value we should use orElseGet.
Fast track reading
- OrElse method in optional takes a parameter
- OrElseGet method in optional needs a supplier function
- In case of orElse method, else part is computed even if value is present
- In case of orElseGet method, else part is computed only if Optional object is empty
- For fixed value orElse method should be used
- If we need to compute value at run time we should use orElseGet