java.util.Optional class defined in Java 8 can be thought of as a container class for storing and handling not – null objects. When working with an Optional, a null value is usually represented as an absent value instead.
The Optional class exposes various methods to help us treat values as either ‘Available’ or ‘Unavailable’. It helps in avoiding all the NullPointerException related checks in our code, making it look cleaner.
java.util.Optional is a final class:
public final class Optional<T> extends Object
Let’s explore the methods available in the Optional class.
static method which returns an empty Optional.
Optional<String> optEmpty = Optional.empty();
Returns true, if an Optional value is present, false otherwise.
Optional<String> optEmpty = Optional.empty(); if(optEmpty.isPresent()) { //returns false ... }
If Optional is present, this method Invokes a consumer passing in the Optional value.
//Signature void ifPresent(Consumer<? super T> consumer) //Usage Optional<String> optStr = Optional.of("programmerGirl"); optStr.ifPresent(System.out::println); //prints programmerGirl
These methods help us instantiate an Optional.
static <T> Optional<T> of(T value) // only accepts not-null value as input static <T> Optional<T> ofNullable(T value) // accepts both null and not null value as input
ofNullable() method accepts both null and not-null Optional values as an input. If a null value is passed, it creates an empty Optional.
Returns the Optional value, if present. Throws a NoSuchElementException for an empty Optional.
//Signature T get() //Usage System.out.println(optStr.get()); //prints programmerGirl optEmpty.get();// throws NoSuchElementException
When we’re not sure if our Optional is empty or not, it isn’t a good idea to use get() method directly. We can rather use orElse() and orElseGet() methods.
//Signatures T orElse(T other) T orElseGet(Supplier<? extends T> other) //Usage String name1 = optStr.orElse("Default"); // name1 = "programmerGirl" String name2 = optEmpty.orElse("Default"); //name2 = "Default" name1 = optStr.orElseGet(() -> "Default"); // name1 = "programmerGirl" name2 = optEmpty.orElseGet(() -> "Default"); //name2 = "Default"
For an empty Optional, orElse() returns the value passed to it as an argument. Similarly, for an empty Optional, orElseGet() method returns the value received from the Supplier method passed in as an argument.
Returns Optional value if present. Throws an exception otherwise.
optEmpty.orElseThrow(IllegalArgumentException::new); // throws exception
Returns the Optional as is, if the condition specified as the predicate is met. Or else returns an empty Optional.
Optional<String> opt1 = optStr.filter(str -> str.length() > 4); System.out.println(opt1.get()); //prints "programmerGirl" Optional<String> opt2 = optEmpty.filter(str -> str.length() > 4); System.out.println(opt2.isPresent()); //false
map() accepts a mapper function which transform the element to a different type. If a mapper function returns an Optional itself, we can use flatMap() method. It helps us avoid dealing with Optional<Optional<R>> by flattening the result into an Optional<R>.
//Signature <R>Optional<R> map(Function<? super T,? extends R> mapper) <R> Optional<R> flatMap(Function<? super T,Optional<R>> mapper) //Usage Optional<Integer> optInt1 = Optional.of("10").map(Integer::parseInt); Optional<Integer> optInt2 = Optional.of("10").flatMap((x) -> Integer.parseInt(x));
To understand the difference between map() and flatMap() method, read this article.
In this tutorial, we covered Java 8 Optional class in detail. We also learned using most of the methods exposed in an Optional class.