4.3.  Use the Optional class

[Note]

A java.util.Optional<T> object is either a wrapper for an Object of type T or a wrapper for no object. It is intended as a safer alternative than a reference of type T that refers to an Object or null.

Following is the declaration for java.util.Optional<T> class:


public final class Optional<T> extends Object {
    ...
}

					

Creating Optional objects

The first step before working with Optional is to learn how to create optional objects. There are several ways:

Unwrapping an Optional

The Optional class provides several instance methods to read the value contained by an Optional instance.

Converting an Optional into a Stream

The Optional.stream() method allows you to convert an Optional to a Stream.

If the Optional contains a value, it will return a Stream containing only that value, otherwise, it will return an empty Stream:


Optional<Integer> in = Optional.of(1);
in.stream()
    .filter(i -> i > 0)
    .forEach(System.out::println);

					

1
					

The Optional.stream() method can be helpful when you are dealing with a stream of Optional elements. It will help to filter out empty optionals and keep the ones with values.

Assume we have a list of optionals received from a method, and some of the optionals are empty:


Stream<Optional<String>> stream = Stream.of(
    Optional.of("Java"),
    Optional.empty(), 
    Optional.of("is"),
    Optional.empty(), 
    Optional.of("good"));

					

In Java 8.0 you could remove empty optionals as follows:


List<String> list = stream
    .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
    .collect(Collectors.toList());

					

In Java 9.0 and later you can remove empty optionals with shorter code using flatMap():


List<String> list = stream 
    .flatMap(Optional::stream)
    .collect(Collectors.toList());

					

The map() and flatMap() in Optional

[Important]

Both Optional.map() and Optional.flatMap() return an Optional.

Use Optional.map() if the function returns the object you need; or Optional.flatMap() if the function returns an Optional.

If the function returns the exact type we need:


Optional<String> s = Optional.of("Java");
s = s.map(String::toUpperCase); // function returns String
s.ifPresent(System.out::print);

					 

If we have a function that returns an Optional then using map() would lead to a nested structure of optionals, as the map() does an additional wrapping. Use flatMap() to keep a flat structure:


Optional<String> s = Optional.of("Java");
s = s.flatMap(val -> Optional.of(val.toUpperCase())); // function returns Optional<String>
s.ifPresent(System.out::print);

					 

Professional hosting         Exam 1Z0-817: Upgrade OCP Java 6, 7 & 8 to Java SE 11 Developer Quiz     Exam 1Z0-810: Upgrade to Java SE 8 Programmer Quiz