Syntax
Optional<Type> opt = Optional.of(value);Examples
Creating an Optional
The three main ways to construct an Optional.
import java.util.Optional;
Optional<String> present = Optional.of("Hello");
Optional<String> empty = Optional.empty();
String maybeNull = null;
Optional<String> safe = Optional.ofNullable(maybeNull); // becomes empty, no exception
System.out.println(present.isPresent()); // true
System.out.println(empty.isPresent()); // falseSafely Retrieving Values
Using orElse() and orElseGet() to provide a fallback instead of risking a NullPointerException.
import java.util.Optional;
Optional<String> username = Optional.empty();
String result = username.orElse("Guest");
System.out.println(result); // Guest
String result2 = username.orElseGet(() -> "Anonymous-" + System.currentTimeMillis());
System.out.println(result2);
// username.get(); // would throw NoSuchElementException - avoid calling get() directlyifPresent() and ifPresentOrElse()
Running code conditionally based on whether a value exists, without an explicit if statement.
import java.util.Optional;
Optional<String> email = Optional.of("fola@example.com");
email.ifPresent(e -> System.out.println("Sending to: " + e));
Optional<String> missingEmail = Optional.empty();
missingEmail.ifPresentOrElse(
e -> System.out.println("Sending to: " + e),
() -> System.out.println("No email on file")
);Chaining map() and filter() on Optional
Optional supports its own map/filter for transforming a value only if it is present.
import java.util.Optional;
Optional<String> name = Optional.of("fola");
Optional<String> upper = name
.map(String::toUpperCase)
.filter(n -> n.length() > 3);
System.out.println(upper.orElse("N/A")); // FOLABest practices
- Use Optional as a return type to signal a value might be absent, but avoid using it for fields or method parameters - that is not its intended purpose
- Prefer orElse()/orElseGet()/ifPresent() over calling .get() directly, which defeats the purpose by risking an exception just like a null check would
- Use Optional.ofNullable() when wrapping a value that might legitimately be null, and Optional.of() only when you are certain the value is non-null
- Chain .map() and .filter() on an Optional to transform a value safely, only if it is actually present, avoiding nested if statements
At a glance
- Purpose
- General-purpose application development
- File extension
- .java
- Runs in
- Java Virtual Machine
- Usually used with
- JDK and Java libraries
Specifications & further reading
Related Java documentation
A lambda expression is a compact way to represent an anonymous function - a block of code that can be passed around as a value. Lambdas work with functional interfaces (interfaces with exactly one abstract method), letting you replace a full anonymous class implementation with a short, focused expression. Lambdas are the foundation that makes Java's Stream API and functional-style programming possible.Stream Basics (map, filter, forEach)
The Stream API, introduced in Java 8, provides a functional, declarative way to process sequences of elements from collections, arrays, or other sources. A stream pipeline consists of a source, zero or more intermediate operations (like filter and map, which are lazy and return a new stream), and exactly one terminal operation (like forEach or collect) that actually triggers processing.Stream Terminal Operations
Terminal operations are what actually trigger a stream pipeline to execute and produce a final result, consuming the stream in the process - after a terminal operation runs, the stream cannot be reused. Common terminal operations include reduce() for combining elements into a single value, count(), sum-style operations for numeric streams, anyMatch()/allMatch() for boolean checks, and findFirst() for retrieving a single element.Collectors
Collectors, used with the stream terminal operation collect(), provide ready-made ways to accumulate stream elements into a final result - a List, Set, Map, a joined String, or grouped/partitioned data. The java.util.stream.Collectors class offers factory methods like toList(), joining(), groupingBy(), and counting() that cover the vast majority of real-world aggregation needs.