Mastering Java Streams API – Complete Guide with Intermediate & Terminal Operations

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.