Module Review: Streams & Lambdas
[!NOTE] This module explores the core principles of Module Review: Streams & Lambdas, deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.
1. Key Takeaways
- Declarative Style: Java 8 introduced functional programming to write code that focuses on what to do (filter, map) rather than how to loop.
- Lambdas & Interfaces: Lambda expressions
(args) → bodyare concise implementations of Functional Interfaces (interfaces with a single abstract method). - Stream Pipeline: A stream consists of a Source, zero or more Intermediate Operations (lazy), and a Terminal Operation (eager).
- Lazy Evaluation: Intermediate operations (like
filter,map) do not execute until a terminal operation (likecollect,forEach) is invoked. - Parallelism:
parallelStream()uses the ForkJoinPool to split tasks across threads. It is beneficial for large datasets or CPU-intensive tasks (NQ > 10,000) but adds overhead for small tasks. - No Boxing: Use
IntStream,LongStream, orDoubleStreamto avoid the memory overhead of boxing primitives into Objects.
2. Interactive Flashcards
Test your recall of the core concepts. Click or press Space/Enter to flip.
What is a Functional Interface?
An interface with exactly one abstract method. It can be implemented by a Lambda Expression.
Is filter() intermediate or terminal?
Intermediate. It returns a new Stream and is lazily evaluated.
What happens if you don't call a terminal operation?
Nothing! Intermediate operations are lazy and won't execute without a terminal operation to trigger the pipeline.
What is the purpose of flatMap()?
To flatten nested structures. It transforms each element into a stream of elements, then concatenates them into a single stream.
When should you use parallelStream()?
When N × Q > 10,000 (Large dataset or expensive operation) and tasks are stateless/independent.
What is IntStream?
A specialized stream for primitive int values that avoids the overhead of boxing/unboxing Integer objects.
3. Cheat Sheet
Common Functional Interfaces
| Interface | Signature | Usage |
|---|---|---|
Predicate<T> |
boolean test(T) |
filter() |
Function<T, R> |
R apply(T) |
map() |
Consumer<T> |
void accept(T) |
forEach() |
Supplier<T> |
T get() |
generate() |
UnaryOperator<T> |
T apply(T) |
iterate() |
BinaryOperator<T> |
T apply(T, T) |
reduce() |
Stream Operations
| Operation | Type | Description |
|---|---|---|
filter(p) |
Intermediate | Keep elements matching predicate |
map(f) |
Intermediate | Transform elements |
flatMap(f) |
Intermediate | Flatten nested streams |
distinct() |
Intermediate | Remove duplicates |
sorted() |
Intermediate | Sort elements |
limit(n) |
Intermediate | Truncate stream |
peek(c) |
Intermediate | Debug stream (observe elements) |
collect(c) |
Terminal | Accumulate into List/Set/Map |
forEach(c) |
Terminal | Perform action for each element |
reduce(acc) |
Terminal | Combine into single result |
count() |
Terminal | Count elements |
anyMatch(p) |
Terminal | True if any match (Short-circuit) |
findFirst() |
Terminal | Returns Optional<T> |
Collectors
| Collector | Result |
|---|---|
toList() |
List<T> |
toSet() |
Set<T> |
joining(del) |
String |
groupingBy(f) |
Map<K, List<T>> |
partitioningBy(p) |
Map<Boolean, List<T>> |
counting() |
Long |
Primitive Streams
| Stream Type | Usage | Benefit |
|---|---|---|
IntStream |
IntStream.range(0, 100) |
No Integer boxing |
LongStream |
LongStream.rangeClosed(1, N) |
64-bit integers |
DoubleStream |
DoubleStream.of(1.5, 2.0) |
Floating point |
Java Course Glossary
Check the glossary for definitions of all terms used in this module.