Optional is a container object introduced which is used to represent a value
that may or may not be present. An Optional object can either contain a
non-null value (in which case it is considered present), or it can contain no
value at all (in which case it is considered empty).
The advantages of Optional:
-
Null Safety: Optional forces you to handle the case where the value is
absent, reducing the risk ofNullPointerException. It provides a clear and
explicit way to signal that a method might not always return a value. -
Improved Code Readability: Optional can help in writing a neat code without
using too many null checks. By usingOptional, we can specify alternate
values to return or alternate code to run. This makes the code more readable
because the facts which were hidden are now visible to the developer. -
Fluent Functional Programming Style: We can use the
Optionalclass to wrap
our data and avoid the classical null checks and some of the try-catch
blocks3. As a result, we’ll be able to chain method calls and have more
fluent, functional code. -
API Design: Optional helps to create clear and robust APIs. It makes it
explicit to the API user that a returned value can be null, and forces them to
handle that case.
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;
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(
new Random().nextInt(words.size())));
word.ifPresent(System.out::println);
}
}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!");
}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);
}
}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);
}
}import java.util.Optional;
void main() {
Optional<String> word1 = Optional.of("sky");
Optional<String> word2 = Optional.empty();
System.out.println(word1.orElse("n/a"));
System.out.println(word2.orElse("n/a"));
}import java.util.Arrays;
import java.util.Optional;
void main() {
var words = Arrays.asList("rock", null, "mountain",
null, "falcon", "sky");
for (String val : words) {
Optional<String> word = Optional.ofNullable(val);
word.ifPresentOrElse(System.out::println,
() -> System.out.println("Invalid value"));
}
}import java.util.Arrays;
import java.util.Optional;
void main() {
var words = Arrays.asList("rock", null, "mountain",
null, "falcon", "sky");
for (String s : words) {
Optional<String> word = Optional.ofNullable(s);
if (word.isPresent()) {
System.out.println(word.get());
} else {
System.out.println("Invalid value");
}
}
}import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
void main() {
List<String> words = new ArrayList<>();
words.add("sky");
words.add(null);
words.add("rock");
words.add("atom");
var res4 = getRandomElement(words);
res4.ifPresentOrElse((e) -> {System.out.println(e.toUpperCase());}, () -> {System.out.println("N/A");});
}
public <T> Optional<T> getRandomElement(List<T> list) {
Collections.shuffle(list);
return Optional.ofNullable(list.get(0));
}import java.util.Optional;
import java.util.function.Function;
// if the result is already an Optional flatMap
// does not wrap it within an additional Optional
void main() {
Function<String, Optional<String>> upperCase = s -> (s == null) ? Optional.empty() : Optional.of(s.toUpperCase());
Optional<String> word = Optional.of("falcon");
Optional<Optional<String>> opt1 = word.map(upperCase);
Optional<String> opt2 = word.flatMap(upperCase);
opt1.ifPresent(s -> s.ifPresent(System.out::println));
opt2.ifPresentOrElse(System.out::println,
() -> System.out.println("Invalid value"));
}