Contents
- Creating an Optional
- Checking for a Value
- Retrieving the Value
- Transforming with map() and flatMap()
- Filtering with filter()
- Practical Example
- Best Practices
// 1. Empty Optional — holds no value
Optional<String> empty = Optional.empty();
// 2. Non-null value — throws NullPointerException if value is null
Optional<String> present = Optional.of("hello");
// 3. Nullable value — wraps null in an empty Optional instead of throwing
Optional<String> nullable = Optional.ofNullable(null); // same as Optional.empty()
Optional<String> nullable2 = Optional.ofNullable("world"); // same as Optional.of("world")
Optional<String> opt = Optional.of("Java");
opt.isPresent(); // true — value is present
opt.isEmpty(); // false — Java 11+
Optional<String> empty = Optional.empty();
empty.isPresent(); // false
empty.isEmpty(); // true
Optional<String> opt = Optional.ofNullable(getValue()); // may be null
// get() — throws NoSuchElementException if empty; AVOID using directly
String s1 = opt.get();
// orElse() — return default value if empty (default always evaluated)
String s2 = opt.orElse("default");
// orElseGet() — return result of Supplier; lazy (only called if empty)
String s3 = opt.orElseGet(() -> computeDefault());
// orElseThrow() — throw custom exception if empty
String s4 = opt.orElseThrow(() -> new IllegalStateException("Value missing"));
// ifPresent() — execute consumer only if value present
opt.ifPresent(v -> System.out.println("Found: " + v));
// ifPresentOrElse() — Java 9+
opt.ifPresentOrElse(
v -> System.out.println("Found: " + v),
() -> System.out.println("Not found")
);
Prefer orElseGet() over orElse() when the default involves an expensive computation or method call, because orElse() always evaluates its argument.
map() applies a function to the value if present and wraps the result in a new Optional.
flatMap() is used when the mapping function itself returns an Optional, avoiding a nested Optional<Optional<T>>.
Optional<String> name = Optional.of(" alice ");
// map — trim and uppercase
Optional<String> upper = name.map(String::trim).map(String::toUpperCase);
upper.ifPresent(System.out::println); // ALICE
// Without Optional (old style — prone to NPE):
String result = null;
String raw = getName();
if (raw != null) {
result = raw.trim().toUpperCase();
}
// flatMap — when the mapper returns Optional itself
class User {
Optional<Address> getAddress() { return Optional.ofNullable(address); }
}
class Address {
Optional<String> getCity() { return Optional.ofNullable(city); }
}
// flatMap avoids Optional<Optional<String>>
Optional<String> city = getUser()
.flatMap(User::getAddress)
.flatMap(Address::getCity);
filter() takes a predicate. If the value is present and passes the predicate, it returns the same Optional; otherwise it returns an empty Optional.
Optional<Integer> age = Optional.of(25);
Optional<Integer> adult = age.filter(a -> a >= 18);
adult.isPresent(); // true
Optional<Integer> minor = Optional.of(15).filter(a -> a >= 18);
minor.isPresent(); // false — 15 < 18 so filter returns empty
A service method that looks up a user by ID and returns the user's email in uppercase:
public Optional<String> findUserEmailById(int id) {
return userRepository.findById(id) // returns Optional<User>
.filter(User::isActive) // keep only active users
.map(User::getEmail) // Optional<String>
.map(String::toUpperCase); // transform email
}
// Caller:
String email = findUserEmailById(42)
.orElse("unknown@example.com");
- Do not use Optional as a field type — it is not Serializable; use it only as method return types.
- Do not use Optional as a method parameter — callers can still pass null; use method overloading instead.
- Avoid calling get() without checking isPresent() — defeats the purpose; use orElse / orElseGet.
- Do not use Optional for collections — return an empty collection instead of Optional<List>.
- Use for return values only — to signal that a result might be absent, replacing null return.
Optional adds a small object-allocation overhead. In performance-critical inner loops, plain null checks may be preferable.