Java Optional
Java Optional
In the HashMap chapter, you used get() to find a value by its key. But what if the key does not exist? Then get() returns null, which means "no value".
If you forget to check for null and use the value anyway, the program crashes:
Example
HashMap<String, String> capitalCities = new HashMap<String, String>();
capitalCities.put("England", "London");
capitalCities.put("Norway", "Oslo");
String city = capitalCities.get("Spain");
System.out.println(city.toUpperCase()); // Error
"Spain" is not in the map, so city is null. Calling toUpperCase() on null stops the program with a NullPointerException.
An Optional solves this. It is like a box that either holds a value or is empty. Before you can use the value, you have to open the box, so you always decide what should happen when it is empty.
Create an Optional
Import java.util.Optional, and create an Optional with one of these methods:
Optional.of(value)creates a box with a valueOptional.empty()creates an empty boxOptional.ofNullable(value)creates a box with the value, or an empty box if the value isnull
The type inside <> tells Java what the box can hold, just like with ArrayList<String>. Use isPresent() to check if the box has a value:
Example
import java.util.Optional;
public class Main {
public static void main(String[] args) {
Optional<String> name = Optional.of("Liam");
Optional<String> noName = Optional.empty();
System.out.println(name.isPresent()); // true
System.out.println(noName.isPresent()); // false
}
}
Get the Value with orElse()
The orElse() method returns the value if there is one. If the box is empty, it returns the default value that you give it:
Example
Optional<String> name = Optional.of("Liam");
Optional<String> noName = Optional.empty();
System.out.println(name.orElse("Guest")); // Liam
System.out.println(noName.orElse("Guest")); // Guest
Note: An Optional also has a get() method, but it gives an error if the box is empty. Use orElse(), or check with isPresent() first.
Run Code If There Is a Value
The ifPresent() method runs code only when the box has a value. You give it the code as a lambda expression:
Example
Optional<String> name = Optional.of("Liam");
name.ifPresent(n -> System.out.println("Hello " + n)); // Hello Liam
If name was empty, nothing would be printed.
Real-Life Example
Optional is most useful as the return value of a method that might not find anything. Here is the capital cities example from the start of this page, now with Optional:
Example
import java.util.HashMap;
import java.util.Optional;
public class Main {
static Optional<String> findCapital(String country) {
HashMap<String, String> capitalCities = new HashMap<String, String>();
capitalCities.put("England", "London");
capitalCities.put("Norway", "Oslo");
return Optional.ofNullable(capitalCities.get(country));
}
public static void main(String[] args) {
System.out.println(findCapital("Norway").orElse("Not found")); // Oslo
System.out.println(findCapital("Spain").orElse("Not found")); // Not found
}
}
The method returns an Optional<String> instead of a String. This shows everyone who uses the method that the result can be missing, and orElse() handles that case without a crash.