Explain Codes LogoExplain Codes Logo

Functional style of Java 8's Optional.ifPresent and if-not-Present?

java
functional-programming
optional-class
java-8
Nikita BarsukovbyNikita Barsukov·Dec 24, 2024
TLDR
optional.ifPresentOrElse(System.out::println, () -> System.err.println("Missing"));

With ifPresentOrElse, you can execute an action if a value is present (System.out::println), or perform an alternative action when absent (System.err.println("Missing")). This is a functionality of elegance and clarity.

Performing dual actions with Optional

To enhance the ifPresentOrElse behaviour, customize it for the business logic. For example, consider the scenario where you handle an entity in a database. If the Optional entity is present, update it; otherwise create a new one.

optional.ifPresentOrElse( existingEntity -> repository.save(existingEntity.updateWith(newData)), // Business as usual () -> repository.save(new Entity(newData)) // Fresh piece in town, everybody! );

Towards maintainable code with the OptionalConsumer

To manage reusable ifPresent/ifNotPresent workflows more efficiently, we can define a custom OptionalConsumer class. This allows us to maintain a clean encapsulation of the ifPresent and ifNotPresent logic as well as reusable code.

public class OptionalConsumer<T> { private Optional<T> optional; private Consumer<T> consumer; private Runnable emptyAction; private OptionalConsumer(Optional<T> optional) { this.optional = optional; } public static <T> OptionalConsumer<T> of(Optional<T> optional) { return new OptionalConsumer<>(optional); // Your one-stop shop for all things Optional } public OptionalConsumer<T> ifPresent(Consumer<T> consumer) { this.consumer = consumer; return this; } public OptionalConsumer<T> ifNotPresent(Runnable emptyAction) { this.emptyAction = emptyAction; return this; } public void execute() { optional.ifPresentOrElse(consumer, emptyAction); } }

Using the OptionalConsumer in a builder-pattern like way, ending with an execute() call.

OptionalConsumer.of(optional) .ifPresent(value -> System.out.println("Processing: " + value)) // Ready for some action! .ifNotPresent(() -> System.err.println("No data to process")) // Guess it's coffee break then... .execute();

This adds to the overall readability and maintainability of your codebase.

Applying transformations to Optionals

To perform transformations based on the presence or absence of a value, Optional.map followed by orElse is your key to success.

String result = optionalString .map(String::toUpperCase) // Pump up the volume! .orElse("DEFAULT"); // Silently singing *I will survive* in the corner

Filter unwanted Optional values

Use Optional.filter to apply predicates before deciding on further conditional actions.

Optional<String> filtered = optionalString.filter(s -> s.length() > 3); filtered.ifPresent(System.out::println); // Bask in the glory of exclusiveness!

This way, you can filter optional's value based on a condition before making further decisions.

Handling empty Optionals without stress

For the scenarios where an Optional is expected to contain a value and its absence is considered exceptional, orElseThrow allows you to throw an exception as easy as a pie.

String value = optionalString.orElseThrow(IllegalStateException::new); // No value found? It's a crime scene!

Thus, not only does it provide clear flow of control but can also communicate specific exceptional conditions.

Functional Coding with Optionals

Whether you use Java 9's ifPresentOrElse or the functionalities of Java 8, functional style injects a new level of precision and clarity in your code. It provides a clear handle to deal with values that may or may not be present, promoting cleaner and more intuitive control flows.