Lambdas, Streams, and Functional Interfaces
Domain 5 tests functional interfaces, method references, and the lazy/eager split in a Stream pipeline: which operations are intermediate, which are terminal, and what actually executes.
Functional interfaces
- A functional interface has exactly one abstract method;
@FunctionalInterfacemakes the compiler enforce that.defaultandstaticmethods do not count toward the single abstract method. - Core
java.util.functiontypes:Function<T,R>,BiFunction,Supplier<T>,Consumer<T>,Predicate<T>,UnaryOperator<T>, plus primitive variants such asIntStreamandIntUnaryOperator. - Lambdas capture effectively final locals; they cannot reassign them.
Method references
Four forms: Type::staticMethod, instance::instanceMethod, Type::instanceMethod (the first argument becomes the receiver), and Type::new.
Streams
- A pipeline is a source, zero or more lazy intermediate operations (
filter,map,flatMap,distinct,sorted,limit,peek), and exactly one terminal operation (forEach,collect,reduce,count,anyMatch,findFirst). - Nothing executes until the terminal operation is invoked. A stream can be consumed only once; reuse throws
IllegalStateException. - Collectors:
toList,toSet,groupingBy,partitioningBy(always two keys,trueandfalse),joining,counting,mapping. Optionalmodels a possibly absent value;orElseis evaluated eagerly,orElseGetlazily.
Worked example
Stream.of("a", "bb", "ccc")
.filter(s -> { System.out.print("F"); return s.length() > 1; })
.map(String::length)
.forEach(System.out::print);
// F2F3
Each element flows through the entire pipeline before the next element is processed, so output interleaves rather than appearing in phases.
Traps
maptransforms one element;flatMapflattens a stream of streams into a single stream.sorted()on non-Comparableelements throwsClassCastExceptionunless a comparator is supplied.- Parallel streams help only large, independent, CPU-bound work; shared mutable state breaks them.