A function gives behavior a name and a boundary: inputs enter, a result or effect follows. In functional programming, the useful ideal is a small, predictable transformation whose purpose remains visible while control mechanics recede. Treating behavior as a focused unit makes larger code read as a sequence of transformations rather than a tangle of steps. section 6.1.2 section 6.2
A pure function depends only on its inputs, returns the same output for the same inputs, and does not modify external or mutable shared state. That makes it referentially transparent: replacing a call with its result does not change behavior. Purity improves local reasoning, testing, thread safety, composition, and readability because the function can be understood without tracking hidden state. section 6.1.2
Figure 6.1 Pure function illustrated as an isolated transformation: inputs enter the function, and a single output is produced. The function depends only on its inputs and does not interact with external state. As a result, the same inputs always produce the same output.
View a pure function as an isolated transformation: values go in, one result comes out, and external state stays outside the boundary. section 6.1.2
Use a function boundary to make intent and tradeoffs explicit:
- Keep one responsibility per function so its transformation is easy to state and test. section 6.1.2
- Prefer pure behavior when the work can be expressed from input values alone; compose small functions to build larger behavior. section 6.1.2
- Treat database writes, HTTP requests, clock reads, global-counter updates, and other external interactions as impure; use them deliberately and justify them when needed. section 6.1.2
- Choose an existing Java functional interface when its signature fits instead of creating a custom one. section 6.2
In Java, a function is represented through a functional interface: an interface with exactly one unimplemented method. `@FunctionalInterface` is optional, but it asks the compiler to protect that one-method rule. Java supplies reusable signatures such as `Predicate`, `Function`, `Consumer`, and `Supplier`; a custom interface is for behavior no existing signature expresses. section 6.2
Replace ceremony with the behavior that matters
A `StringPredicate` can declare `boolean test(String value)`, and a `LengthGreaterThanThree` class can implement it. For one small behavior, the class is mostly ceremony. A lambda retains the essential transformation: `StringPredicate myTestingFunction = x -> x.length() > 3;` `boolean isValid = myTestingFunction.test("hello");` The arrow separates parameters from the body. With a single abstract method available, Java can infer the implementation target, leaving the reader focused on the test rather than on a class wrapper. section 6.2 section 6.2.1
Lambdas provide concise anonymous functions, but their value is more than brevity: they let behavior be stored, returned, passed to another method, and invoked later. A predicate can sit in a list, be returned by a method, or be supplied directly as an argument. This first-class treatment turns behavior into data that can be assembled where it is most readable. section 6.2.1
Figure 6.2 A functional pipeline: transforming raw data
Follow how independently useful functions become more expressive when chained: each pipeline stage represents behavior and the data flows through its transformations. section 6.3
Do not make purity a rigid excuse to ignore the real world. Imperative code remains appropriate when work must follow a precise sequence, change state over time, or interact with files, databases, and external services. The practical heuristic is to isolate those effects where possible, and keep ordinary transformations small, explicit, and composable. section 6.1.2 section 6.1.2



















