GotchaDifficulty: Intermediate1 min

Why orElse Ran Your Fallback Even Though the Value Was There

A cache lookup that hits every time, and a database query in the logs for every one of those hits. The fallback is inside an orElse that should never be reached.

java
Customer c = cached(ref).orElse(loadFromDatabase(ref));

orElse is an ordinary method taking an ordinary argument, and Java evaluates arguments before calling. loadFromDatabase(ref) runs first, every time, and its result is then handed to an orElse that usually discards it.

What runs, with a value present
WrittenThe fallback runsThe result
orElse(loadFromDatabase(ref))Yes, and is thrown awayThe cached value
orElseGet(() -> loadFromDatabase(ref))NoThe cached value

The lambda in orElseGet is what defers the work: nothing inside it runs until orElseGet decides to call it. Use orElse only for a value you already have.

java
Customer c = cached(ref).orElseGet(() -> loadFromDatabase(ref));