Java Optional
last modified July 7, 2024
In this article we work with Optional type in Java.
Optional is a container object which may or may not contain a value.
We can check if a value is present with isPresent and then retrive
it with get. If the container does not contain a value it is then
called empty.
The goal of the Optional type is to avoid null references and all
the problems that are caused by them.
The Optional was inspired by similar types found in Haskell and
Scala. Other languages, such as C# or Groovy, use null-safe operators
.? for the same purpose.
Optional<String> empty = Optional.empty();
We create an empty Optional with Optional.empty.
It is used insted of null references.
Optional<String> word = Optional.of("falcon");
Optional.of is used when we are certain that the parameter will not 
be null.
Optional<String> word = Optional.ofNullable(value);
Optional.ofNullable is used when we don't know if there will be 
null.
Simple example
In the following example, we have a simple example with Optional
type.
import java.util.Arrays;
import java.util.Optional;
void main() {
    var words = Arrays.asList("rock", null, "mountain",
            null, "falcon", "sky");
    for (int i = 0; i < 5; i++) {
        Optional<String> word = Optional.ofNullable(words.get(i));
        word.ifPresent(System.out::println);
    }
}
We have a list of words; the list also contains null values. We go through the list and print the elements.
Optional<String> word = Optional.ofNullable(words.get(i));
We know that we can get a null value from the list; therefore, we wrap the
element into Optional with Optional.ofNullable.
word.ifPresent(System.out::println);
We check if there is some value in the Optional with
ifPresent. If case there is one, we print it.
In the following example, we have three methods that return an
Optional type.
import java.util.Optional;
void main() {
    if (getNullMessage().isPresent()) {
        System.out.println(getNullMessage().get());
    } else {
        System.out.println("n/a");
    }
    if (getEmptyMessage().isPresent()) {
        System.out.println(getEmptyMessage().get());
    } else {
        System.out.println("n/a");
    }
    if (getCustomMessage().isPresent()) {
        System.out.println(getCustomMessage().get());
    } else {
        System.out.println("n/a");
    }
}
Optional<String> getNullMessage() {
    return Optional.ofNullable(null);
}
Optional<String> getEmptyMessage() {
    return Optional.empty();
}
Optional<String> getCustomMessage() {
    return Optional.of("Hello there!");
}
The three methods return a null message, an empty message and a real message.
if (getNullMessage().isPresent()) {
    System.out.println(getNullMessage().get());
} else {
    System.out.println("n/a");
}
First, we check if the value returned by the method contains a value with
isPresent. If true, we get the value with get.
Otherwise we print "n/a" message.
Optional ifEmpty
The ifEmpty returns true, if the value is not present. 
import java.util.Arrays;
import java.util.Optional;
void main() {
    var words = Arrays.asList("rock", null, "mountain",
            null, "falcon", "sky");
    for (int i = 0; i < 5; i++) {
        Optional<String> word = Optional.ofNullable(words.get(i));
        if (word.isEmpty()) {
            System.out.println("n/a");
        }
        word.ifPresent(System.out::println);
    }
}
In the example, we print all valid values with ifPresent. All empty 
values are recognized via isEmpty.
Optional orElse
The orElse method allows us to quickly return a value if it is not
present.
import java.util.Optional;
void main() {
    System.out.println(getNullMessage().orElse("n/a"));
    System.out.println(getEmptyMessage().orElse("n/a"));
    System.out.println(getCustomMessage().orElse("n/a"));
}
Optional<String> getNullMessage() {
    return Optional.ofNullable(null);
}
Optional<String> getEmptyMessage() {
    return Optional.empty();
}
Optional<String> getCustomMessage() {
    return Optional.of("Hello there!");
}
We managed to shorten the example a bit with orElse method.
In this article we covered the Optional type in Java.
Optional flatMap
The flatMap method applies the provided  mapping function to a
value if it is present. It returns that result or otherwise an empty
Optional. If the result is already an Optional,
flatMap does not wrap it within an additional
Optional.
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Function;
void main() {
    Function<String, Optional<String>> upperCase = s -> Optional.of(s.toUpperCase());
    var words = Arrays.asList("rock", null, "mountain",
            null, "falcon", "sky");
    for (int i = 0; i < 5; i++) {
        Optional<String> word = Optional.ofNullable(words.get(i));
        var res = word.flatMap(upperCase);
        res.ifPresent(System.out::println);
    }
}
JSoup example
In the following example, we use JSoup library to parse and modify an HTML document.
For the project, we need the jsoup artifact. 
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import java.util.Optional;
void main() {
    String htmlString = """
            <html>
            <head>
            <title>My title</title>
            </head>
            <body>
            <main></main>
            </body>
            </html>
            """;
    var doc = Jsoup.parse(htmlString);
    Optional<Element> mainEl = Optional.ofNullable(doc.select("main").first());
    mainEl.ifPresent(e -> {
        e.append("<p>hello there!</p>");
        e.prepend("<h1>Heading</h1>");
    });
    System.out.println(doc);
}
We parse an HTML string and look for the main tag. If it is
present, we append p and h1 tags to the document.
var doc = Jsoup.parse(htmlString);
Optional<Element> mainEl = Optional.ofNullable(doc.select("main").first());
The main tag might not be present and the first method 
in this case will return null. Therefore, we use the 
Optional.ofNullable method. 
mainEl.ifPresent(e -> {
    e.append("<p>hello there!</p>");
    e.prepend("<h1>Heading</h1>");
});
We only call append and prepend methods if the 
Optional contains the main tag.
Jdbi example
The findOne method returns the only row in the result set, if any.  
It returns Optional.empty() if zero rows are returned, or if the  
row itself is null.  
For the example, we need the jdbi3-core and the
postgresql artifacts.
import org.jdbi.v3.core.Jdbi;
import java.util.Optional;
void main() {
    String jdbcUrl = "jdbc:postgresql://localhost:5432/testdb";
    String user = "postgres";
    String password = "s$cret";
    Jdbi jdbi = Jdbi.create(jdbcUrl, user, password);
    int id = 3;
    String query = "SELECT name FROM cars WHERE id = ?";
    Optional<String> res = jdbi.withHandle(handle -> handle.select(query, id)
            .mapTo(String.class)
            .findOne());
    res.ifPresentOrElse(System.out::println, () -> System.out.println("N/A"));
}
In the example, we select a single cell from a row in a table. We print the data  
if it is present or N/A if not.
Source
Java Optional - language reference
In the example, we apply the upperCase function on the list of
words.
Author
List all Java tutorials.