Search

December 30, 2020

Java Joy: Optional orElse orElseGet That Is The Question

The Optional class has the orElse and orElseGet methods to return a value when the Optional object is empty. This is useful to return a default value for example. But there is a small difference between the two methods. The orElseGet method needs a Supplier argument that returns a value of the type of the Optional value. The Supplier is only invoked when the Optional value is empty. The statement passed as argument to the orElse method is always executed, even when the Optional value is not empty. Preferrably we should use orElseGet as it will only invoke statements if needed.

In the following example code we see when our method getDefaultGreeting is invoked by using orElse and orElseGet with an empty and non-empty Optional object:

package mrhaki.optional;

import java.util.Optional;

public class Sample {

    /** 
      * Keep track of total number of times method getDefaultGreeting is invoked.
      */
    private static int totalDefaultGreetingInvoked = 0;

    public static void main(String[] args) {
        // Define an empty optional.
        var name = Optional.ofNullable(null);

        // orElse returns value from argument when optional is empty.
        assert ("Hello " + name.orElse(getDefaultGreeting())).equals("Hello world");
        assert totalDefaultGreetingInvoked == 1;

        // orElseGet needs a Supplier that is executed when the optional is empty.
        assert ("Hello " + name.orElseGet(Sample::getDefaultGreeting)).equals("Hello world");
        assert totalDefaultGreetingInvoked == 2;


        // This time the optional is not empty.
        name = Optional.ofNullable("mrhaki");

        // orElse will always get the value, even when the optional is not empty.
        assert ("Hello " + name.orElse(getDefaultGreeting())).equals("Hello mrhaki");
        assert totalDefaultGreetingInvoked == 3;

        // orElseGet will not call the Supplier when the optional is not empty.
        assert ("Hello " + name.orElseGet(Sample::getDefaultGreeting)).equals("Hello mrhaki");
        assert totalDefaultGreetingInvoked == 3;
    }

    private static String getDefaultGreeting() {
        // Increase counter, so we can check the method is invoked.
        totalDefaultGreetingInvoked++;
        return "world";
    }
}

Written with Java 15.