Functional Programming & Streams

Optional

Optional<T> is a return type that makes "no result" impossible to ignore. Use it for possibly-absent return values; don't use it for fields, parameters, or collections — and never call bare get().
  • Purpose: API honesty — callers must consciously handle absence (EJ 55)
  • Consume with orElse, orElseGet(supplier), orElseThrow, ifPresent, map
  • Never isPresent() + get() when a functional form exists
  • Don't wrap collections in Optional — return the empty collection
  • Skip Optional for performance-critical returns and for fields (use null + discipline there)
  • Optional.stream() bridges into stream pipelines
Consuming an Optional well
Optional<User> found = repo.findByEmail(email);

User user = found.orElseThrow(() -> new NoSuchUserException(email));
String name = found.map(User::name).orElse("anonymous");
found.ifPresentOrElse(this::greet, this::showSignup);

// orElse vs orElseGet — the argument of orElse is ALWAYS evaluated:
config = stored.orElse(loadDefaults());        // loadDefaults runs even when present!
config = stored.orElseGet(this::loadDefaults); // lazy — usually what you meant

Chaining absorbs null-check pyramids: person.flatMap(Person::address).map(Address::city).filter(c -> !c.isBlank()). Each step runs only if a value is present. For interop, Optional.ofNullable(legacyCall()) enters the monad; opt.orElse(null) exits it at legacy boundaries.

Sources
  • Core Java, Volume II: Advanced Features (13th ed.)Ch. 1.7 — The Optional Type
  • Effective Java (3rd ed.)Item 55