Java Streams API – Complete Guide
The Java Streams API, introduced in Java 8, is one of the most powerful tools for functional-style data processing. In this blog, we’ll cover what streams are, how they work, and dive deep into intermediate and terminal operations with clear examples.
๐ What is a Stream in Java?
A stream is a sequence of elements supporting sequential and parallel aggregate operations. It does not store data but works on the data source (like a collection) and processes elements through a pipeline of operations.
๐งฉ Intermediate Operations
Intermediate operations return a new stream and are lazy; they are executed only when a terminal operation is triggered.
Method | Description | Example |
---|---|---|
filter() |
Filters elements based on a condition | stream.filter(x -> x > 5) |
map() |
Transforms each element | stream.map(String::toUpperCase) |
flatMap() |
Flattens nested structures | list.stream().flatMap(List::stream) |
distinct() |
Removes duplicates | stream.distinct() |
sorted() |
Sorts elements | stream.sorted() |
peek() |
Performs action without changing the stream | stream.peek(System.out::println) |
limit() |
Limits the number of elements | stream.limit(3) |
skip() |
Skips the first N elements | stream.skip(2) |
๐ Examples:
// map example
List<Integer> squares = List.of(1, 2, 3, 4)
.stream()
.map(n -> n * n)
.collect(Collectors.toList());
// Output: [1, 4, 9, 16]
// filter example
List<String> result = List.of("apple", "banana", "avocado")
.stream()
.filter(s -> s.startsWith("a"))
.collect(Collectors.toList());
// Output: [apple, avocado]
// flatMap example
List<List<String>> data = List.of(List.of("a", "b"), List.of("c", "d"));
List<String> flat = data.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// Output: [a, b, c, d]
๐ Terminal Operations
Terminal operations consume the stream and trigger the actual processing. After a terminal operation, the stream is no longer usable.
Method | Description | Example |
---|---|---|
forEach() |
Performs an action for each element | stream.forEach(System.out::println) |
collect() |
Converts stream to collection | collect(Collectors.toList()) |
reduce() |
Reduces elements to one result | stream.reduce(0, Integer::sum) |
count() |
Returns the number of elements | stream.count() |
anyMatch() |
Checks if any match a predicate | stream.anyMatch(x -> x > 0) |
allMatch() |
Checks if all match a predicate | stream.allMatch(x -> x != null) |
findFirst() |
Returns the first element | stream.findFirst() |
๐ Examples:
// reduce example
int sum = List.of(1, 2, 3, 4).stream()
.reduce(0, Integer::sum);
// Output: 10
// collect to Map
Map<String, Integer> map = List.of("apple", "banana").stream()
.collect(Collectors.toMap(Function.identity(), String::length));
// Output: {apple=5, banana=6}
// anyMatch example
boolean hasNegative = List.of(1, -1, 5).stream()
.anyMatch(x -> x < 0);
// Output: true
⚡ Pro Tip: Combine Operations
List<String> result = List.of("java", "spring", "hibernate")
.stream()
.filter(s -> s.length() > 5)
.map(String::toUpperCase)
.collect(Collectors.toList());
// Output: [SPRING, HIBERNATE]
✅ Conclusion
The Java Stream API provides a modern, concise, and powerful way to process data. By understanding how intermediate and terminal operations work, you can write cleaner and more efficient Java code.
๐ Related Posts
๐ง Java 8 Interview Questions
Test your knowledge of Java 8 features like Streams, Lambda, and Optional.
๐งช Java Coding Round Qs
Practice common problems solved using Java Streams like grouping, filtering, and mapping.
๐ก Exception Handling Best Practices
Even in Streams, you need to handle exceptions smartly to avoid broken pipelines.
๐ฆ Java 21 Record Patterns
Combine Streams with pattern matching for expressive and modern Java code.