Careeroza
Composing Functions
andThen, compose, and, or, negate
Functional interfaces have default methods to combine small functions into bigger ones, like LEGO blocks.
| Method | On | Meaning |
|---|---|---|
f.andThen(g) | Function, Consumer | run f, then g on the result |
f.compose(g) | Function | run g first, then f |
p.and(q) / p.or(q) | Predicate | logical AND / OR |
p.negate(), Predicate.not(p) | Predicate | logical NOT |
Function.identity() | Function | returns its input unchanged |
Comparator.comparing(...).thenComparing(...) | Comparator | multi-key sorting |
Building a Pipeline
Example
Clean up user input, then validate it with combined predicates.
import java.util.*;
import java.util.function.*;
public class Main {
public static void main(String[] args) {
Function<String, String> trim = String::trim;
Function<String, String> lower = String::toLowerCase;
Function<String, String> normalize = trim.andThen(lower);
Predicate<String> notEmpty = s -> !s.isEmpty();
Predicate<String> hasAt = s -> s.contains("@");
Predicate<String> isGmail = s -> s.endsWith("@gmail.com");
Predicate<String> validEmail = notEmpty.and(hasAt);
List<String> inputs = List.of(" [email protected] ", "[email protected]", " ", "no-at-sign");
for (String in : inputs) {
String email = normalize.apply(in);
System.out.printf("%-20s valid=%-5b gmail=%b%n",
"'" + email + "'", validEmail.test(email), validEmail.and(isGmail).test(email));
}
Function<Integer, Integer> plus2 = x -> x + 2;
Function<Integer, Integer> times3 = x -> x * 3;
System.out.println("plus2.andThen(times3)(5) = " + plus2.andThen(times3).apply(5));
System.out.println("plus2.compose(times3)(5) = " + plus2.compose(times3).apply(5));
}
}Output
'[email protected]' valid=true gmail=true '[email protected]' valid=true gmail=false '' valid=false gmail=false 'no-at-sign' valid=false gmail=false plus2.andThen(times3)(5) = 21 plus2.compose(times3)(5) = 17
Practice
Exercise: Using Predicate.not, remove blank strings from List.of("a", " ", "b", "").
Show answer
List<String> result = List.of("a", " ", "b", "").stream()
.filter(Predicate.not(String::isBlank))
.toList();
System.out.println(result); // [a, b]