Optional Class Overview

Optional class is a nice solution that can be used to solve NullPointerException problem or in such cases when you need to express an empty value. In other words, it can be compared with a box that might contain something or be empty.


The class was introduced in Java 8 and you can see that it’s widely used in Stream API. For instance,  such methods like min, max and average  return Optional. Since the stream source can be empty it’s better to return Optional rather than null. Because Optional class provides rich functionality to handle different scenarios in functional way.

To create an instance of Optional class you can use one of three factory methods:

Optional<String> emptyOptional1 = Optional.ofNullable(null);
Optional<String> nonEmptyOptional1 = Optional.of("Hello");
Optional<String> emptyOptional2 = Optional.empty()

Optional.empty() method as it’s name suggests returns an instance of empty Empty optional. Optional.of() and Optional.ofNullable both return an Optional that contains the given value. But, they behave differently if the given value is null. For example, of() will throw NPE and ofNullable() will return an empty Optional.

Once an instance of Optional class is in your hands you can manipulate it in functional or imperative way.

Optional<String> result = Optional.of("Hello!");

// Imperative
if (result.isPresent()) {
    System.out.println(result.get()); // Hello!

// Functional
result.ifPresent(System.out::println); // Hello!

One important moment here is that you will get NoSuchElementException if you are getting the value from empty Optional. This is why you need to explicitly check the presence of value.

What are the other options if the value is not present? In case you can use one of three “OR” methods:

  1. orElse() – returns the given value in case if Optional is empty.
  2. orElseGet() – the method accepts supplier which will be returned in case if the Optional is empty.
  3. orElseThrow() – throws an exception that was created in the given supplier if Optional is empty.

There are two more methods I would like to discuss: map() and filter().

If Optional value presents the map() method transforms it using the given function. If transformation result is null or Optional is empty the empty optional will be returned.

Optional<String> result = Optional.of("Hello!");

result.map(v -> v.toUpperCase())
        .ifPresent(System.out::println); // HELLO!

In many cases you need to check whether the value  matches some predicate. For these case you can use the filter() method.

Optional<String> result = Optional.of("Hello!");

result.filter(v -> v.startsWith("H"))
        .ifPresent(System.out::println); // Hello!

If a value is present, and the value matches the given predicate, return an Optional describing the value, otherwise return an empty Optional. Do not forget to use ifPresent() or isPresent() methods.