Java Streams
In Java, a Stream represents a sequence of elements that supports sequential and parallel aggregate operations. Streams enable functional-style operations on collections of elements through a declarative API, allowing for efficient data processing with features like filtering, mapping, and reduction.
Key Characteristics:
- Lazy Evaluation: Intermediate operations are only executed when a terminal operation is invoked
- Non-Mutating: Operations return new streams rather than modifying the source
- Pipeline Architecture: Operations can be chained to form complex processing workflows
- Redability: Allow operations on data in clear and concise manner, making the code more readable and maintanable.
Stream Creation Methods
1. From Collections
2. From Arrays
3. Using Stream.of()
4. From Files
Stream Operations
Intermediate Operations
| Operation | Description | Example |
|---|---|---|
filter() |
Selects elements matching a predicate | .filter(s -> s.length() > 5) |
map() |
Applies a function to transform elements | .map(String::toUpperCase) |
distinct() |
Removes duplicate elements | .distinct() |
sorted() |
Orders elements according to natural order or specified comparator | .sorted(Comparator.reverseOrder()) |
limit() |
Restricts stream to first n elements |
.limit(10) |
peek() |
Performs action without modifying stream (debugging helper) | .peek(System.out::println) |
Terminal Operations
| Operation | Description | Example |
|---|---|---|
forEach() |
Executes action for each element | .forEach(System.out::println) |
collect() |
Accumulates elements into collection or summary object | .collect(Collectors.toList()) |
count() |
Returns total number of elements | .filter(s -> !s.isEmpty()).count() |
anyMatch() |
Returns true if any element matches predicate | .anyMatch(s -> s.contains("error")) |
allMatch() |
Returns true if all elements match predicate | .allMatch(s -> s.length() > 0)) |
noneMatch() |
Returns true if no elements match predicate | .noneMatch(s -> s == null)) |
reduce() |
Combines elements using accumulation function | .reduce(0, (a,b) -> a + b)) |
findFirst() |
Returns Optional describing first element | .findFirst() |
Best Practices
-
Prefer Method References:
map(String::length)instead ofmap(s -> s.length()) -
Avoid Side Effects:
Usecollect()before performing output operations -
Reuse Predicates:
- Parallelization:
Use.parallelStream()judiciously for CPU-intensive operations
Performance Considerations
- Stream pipelines execute only when terminal operation is called
- Intermediate operations have O(1) time complexity in isolation
- Complex pipelines may benefit from parallel processing
- Avoid nested streams (consider
flatMap()instead)