Functional, stateless programming expresses behavior as compositions of transformations rather than step-by-step commands. Each small function receives inputs and returns an output; when it depends only on those inputs and avoids side effects or mutable shared state, it is pure and referentially transparent. The result is code whose visible flow emphasizes what must happen while control mechanics recede. section 6.1 section 6.1.2
Purity is a practical constraint, not an aesthetic badge. A pure function returns the same result for the same input, does not alter external state, and can be understood in isolation. That predictability improves testability, reuse, thread safety, and readability because callers need not account for hidden changes. section 1.1.5 section 6.1.2
Describe a word transformation
A pipeline can state the transformation directly: keep words longer than three characters, convert them to uppercase, then collect them. Compared with a loop that creates and mutates a result list, the pipeline makes the data flow and intended result more prominent. section 6.1.2 section 6.1.1
List<String> result = words.stream()
.filter(w -> w.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
This pipeline shows functions composed as successive transformations: filter the input, map each remaining value, and collect the result. section 6.1.2
Declarative composition can also make absence explicit without letting null checks dominate the control flow. Chaining Optional.map navigates from a product to pricing details, selects a price, and extracts its amount; an empty value short-circuits the mapping. The code centers the business purpose—finding a final price—rather than the defensive mechanics. section 1.2.1 section 1.2.2
Stateless functional style does not eliminate imperative code. Writing to a database, sending an HTTP request, reading the clock, or changing shared state is impure and may be necessary. Use functional pipelines where transformations stay clear, but simplify or return to imperative code when pipelines grow long or exception handling obscures intent. section 6.1.2 section 6.5
Choose clarity over a single paradigm
Finding the youngest and oldest people and sorting names can be written with separate streams, lowering cognitive complexity, but it performs multiple traversals. For very large data, parallel streams or a custom collector may address performance; the clearest solution balances those constraints rather than treating functional style as automatic improvement. section 10.2.1 section 10.2.2


















