Search

Dark theme | Light theme
Showing posts with label JavaJoy:Optional. Show all posts
Showing posts with label JavaJoy:Optional. Show all posts

March 24, 2021

Java Joy: Run Action When Optional Value Present Or Not

If we have an Optional instance we can consume the value if it is present using the ifPresent method. Since Java 9 the method ifPresentOrElse has been added to the Optional class. The first argument is of type Consumer and is invoked when there is an optional value. The second argument is of type Runnable and is executed when the the optional is empty. The method in the Consumer and Runnable implementations does not return a type but returns void. Therefore we should use ifPresentOrElse when we need a conditional side effect for an Optional instance.

In the following example we have a method handleName that will update a list if an optional value is present or increases a counter when the optional value is empty:

package mrhaki.optional;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

public class IfPresentOrElse {

    // Store names.
    private static List<String> names = new ArrayList<>();
    
    // Counter for counting empty or null names.
    private static AtomicInteger emptyCounter = new AtomicInteger();

    public static void main(String[] args) {
        // Optional name property will have a value.
        handleName(new User("mrhaki"));

        assert "MRHAKI".equals(names.get(0));
        assert 0 == emptyCounter.get();
        
        // Reset properties
        names.clear();
        emptyCounter.set(0);
        
        // Optional name property is empty.
        handleName(new User());

        assert names.isEmpty();
        assert 1 == emptyCounter.get();
    }

    private static void handleName(User user) {
        user.getName().ifPresentOrElse(
                // If present add name in uppercase to names.
                s -> names.add(s.toUpperCase(Locale.ROOT)),
                // If not present increment the counter.
                emptyCounter::incrementAndGet);
    }

    // Simple class with an optional property name.
    private static class User {
        private final String name;

        private User() {
            this(null);
        }

        private User(final String name) {
            this.name = name;
        }

        Optional<String> getName() {
            return Optional.ofNullable(name);
        }
    }
}

Written with Java 16.

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.