Java Stream API introduced in JDK8 brings functional programmming to Java, enabling declarative data processing for cleaner and more efficient code.
Key Stream Characteristics
- Not a data structure, no internal storage
- No index-based access
- Lazy evaluation
- Parallel processing support
- Easy conversion to arrays/collections
- Supports filtering, mapping, reduction, and aggregation operations
Stream Processing Mechanism Stream operations consist of:
- Source (arrays, collections, I/O channels)
- Intermediate operations (return new streams)
- Terminal operation (triggers processing)
Common Stream Operations
Stream Creaiton
// From array
String[] items = {"apple", "banana", "cherry"};
Stream<String> fruitStream = Arrays.stream(items);
// From collection
List<Integer> numbers = List.of(1, 2, 3);
Stream<Integer> numStream = numbers.stream();
// Generated stream
Stream.generate(() -> Math.random()).limit(5);
// Iterated stream
Stream.iterate(0, n -> n + 2).limit(10);
Intermediate Operations
// Filtering
numbers.stream().filter(n -> n % 2 == 0);
// Mapping
fruitStream.map(String::toUpperCase);
// Sorting
numbers.stream().sorted(Comparator.reverseOrder());
// Distinct elements
Stream.of(1, 1, 2, 3).distinct();
Terminal Operations
// Aggregation
int total = numbers.stream().reduce(0, Integer::sum);
long count = numbers.stream().count();
Optional<Integer> max = numbers.stream().max(Integer::compare);
// Collection
List<String> upperFruits = fruitStream.map(String::toUpperCase).toList();
Set<Integer> uniqueNumbers = numbers.stream().collect(Collectors.toSet());
// Matching
boolean anyMatch = numbers.stream().anyMatch(n -> n > 5);
boolean allMatch = numbers.stream().allMatch(n -> n < 10);
Advanced Stream Techniques
FlatMap for Nested Collections
List<List<String>> nested = List.of(
List.of("a", "b"),
List.of("c", "d")
);
List<String> flat = nested.stream()
.flatMap(List::stream)
.toList();
Custom Collectors
Map<String, Integer> wordCounts = Stream.of("apple", "banana", "apple")
.collect(Collectors.toMap(
Function.identity(),
word -> 1,
Integer::sum
));
Parallel Streams
List<Integer> squares = numbers.parallelStream()
.map(n -> n * n)
.toList();
Stream Pipelines
List<String> result = Stream.iterate(1, n -> n + 1)
.limit(100)
.filter(n -> n % 3 == 0)
.map(n -> "Number " + n)
.skip(5)
.toList();