Replace error-prone null with Optional to signal "maybe no value" and handle the missing case explicitly and safely.
Why: returning null for "nothing found" leads to NullPointerExceptions when callers forget to check. Optional<T> is a small box that either holds a value or is empty, forcing the caller to deal with the empty case on purpose.
import java.util.Optional;
Optional<String> found = Optional.of("Ada"); // has a value
Optional<String> missing = Optional.empty(); // no value
System.out.println(found.isPresent()); // true
System.out.println(missing.isPresent()); // falseWhy: a method that might not find a result should return an Optional instead of null. The caller then cannot ignore the empty possibility. Use Optional.ofNullable when the value might be null.
import java.util.List;
import java.util.Optional;
Optional<String> firstLongName(List<String> names) {
return names.stream()
.filter(n -> n.length() > 4)
.findFirst(); // returns Optional — maybe nothing matched
}Why: never call get() blindly — it throws if empty. orElse provides a fallback value, orElseGet computes one lazily, and orElseThrow raises a clear error when emptiness is truly unexpected.
import java.util.Optional;
Optional<String> name = Optional.empty();
System.out.println(name.orElse("Anonymous")); // "Anonymous"
System.out.println(name.orElseGet(() -> "computed default"));
// name.orElseThrow(); // throws NoSuchElementException if emptyWhy: you can work with the value without ever unwrapping it. map transforms the contents if present (and stays empty otherwise), and ifPresent runs code only when there is a value — no null check needed.
import java.util.Optional;
Optional<String> name = Optional.of("ada");
Optional<String> upper = name.map(String::toUpperCase); // Optional[ADA]
System.out.println(upper.orElse("?")); // "ADA"
name.ifPresent(n -> System.out.println("Hello " + n)); // runs: "Hello ada"