Java Stream API: Pipelines, Filtering, Mapping, Aggregation & Parallel Streams
Welcome to Phase 19: Java Stream API & Pipelines Masterclass! Introduced in Java 8 and continuously enhanced up to Java 21 LTS, the Stream API (java.util.stream) is one of the most powerful features in modern Java. A Stream is not a data structure โ it does not store data. Instead, it is a declarative computational pipeline that processes data sequences from Collections, Arrays, or I/O channels with zero memory mutation, lazy evaluation, and seamless parallel multithreading capability. In this comprehensive in-depth guide, you will master every core stream method, intermediate vs terminal execution models, complex grouping aggregators, and parallel stream performance.
Java lo Stream ante data items เฐฏเฑเฐเฑเฐ continuous sequence paina functional transformations (filter, transform, aggregate) perform chese computation pipeline. Dheeni valla traditional nested for-loops and mutable temporary lists completely eliminate avthayi:
๐ก Collections vs Streams โ Architectural Differences
| Feature | Java Collection (e.g. ArrayList) | Java Stream (java.util.stream) |
|---|---|---|
| Primary Role | Data Storage: Holds elements in Heap memory. | Computation: Processes elements on-demand. |
| Iteration Model | External Iteration: User writes for (int i...) loop explicitly. | Internal Iteration: Stream library manages iteration internally. |
| Execution Timing | Eager: Elements are created & stored immediately. | Lazy: No work is executed until a Terminal Operation is invoked! |
| Reusability | Reusable multiple times. | Consumable Once: Once terminal op runs, the stream is closed! |
| Data Mutation | Directly mutates backing collection (e.g. add(), remove()). | Non-mutating: Never modifies original source data. |
[SOURCE] [INTERMEDIATE OPS (Lazy)] [TERMINAL OP (Eager)]
List<Integer> โโโบ .filter(n -> n % 2 == 0) โโโบ .map(n -> n * 2) โโโบ .forEach(System.out::println)
(Numbers) (Filters Odd numbers) (Doubles evens) (Prints & Executes Pipeline!)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Chain of Lazy Transformations
Java lo streams ni multiple sources nunchi construct cheyyavachu:
import java.util.*;
import java.util.stream.*;
public class StreamSourcesDemo {
public static void main(String[] args) {
// 1. From Collection
List<String> list = List.of("Java", "Spring", "Docker");
Stream<String> s1 = list.stream();
// 2. From Array
String[] arr = {"A", "B", "C"};
Stream<String> s2 = Arrays.stream(arr);
// 3. From Static Values
Stream<Integer> s3 = Stream.of(10, 20, 30);
// 4. Primitive IntStream (Zero Autoboxing Overhead!)
IntStream intStream = IntStream.rangeClosed(1, 5); // 1, 2, 3, 4, 5
// 5. Infinite Streams with limit
Stream<Double> randomNumbers = Stream.generate(Math::random).limit(3);
}
}
Intermediate Operations eppudu kotha Stream ni return chesthayi mariyu Lazy ga untayi โ ante Terminal operation call ayye daka intermediate operations okkati kuda execute avvadhu:
| Method | Argument | Description & Purpose |
|---|---|---|
filter(Predicate) | n -> n > 50 | Selects only elements matching the boolean condition. |
map(Function) | s -> s.toUpperCase() | Transforms each element into another object/value. |
sorted() / sorted(Comparator) | (a, b) -> b - a | Sorts elements in natural or custom comparator order. |
distinct() | none (uses .equals()) | Eliminates all duplicate elements. |
limit(n) | long maxSize | Truncates stream to at most n elements. |
skip(n) | long n | Discards the first n elements (ideal for pagination!). |
import java.util.List;
public class IntermediateOpsDemo {
public static void main(String[] args) {
List<Integer> rawScores = List.of(85, 42, 90, 85, 30, 95, 78, 90, 60);
System.out.println("Top 3 Unique Passing Scores (>= 70):");
rawScores.stream()
.filter(score -> score >= 70) // Filter passing grades
.distinct() // Remove duplicates (85, 90)
.sorted((a, b) -> b - a) // Sort DESCENDING
.limit(3) // Pick top 3
.forEach(System.out::println); // Terminal Op! (95, 90, 85)
}
}
Terminal Operations stream pipeline execution ni trigger chesi non-stream result ni (e.g. single number, List, Map, boolean) return chesthayi:
import java.util.List;
import java.util.Optional;
public class ReductionsDemo {
public static void main(String[] args) {
List<Integer> cartPrices = List.of(1200, 450, 3000, 850, 150);
// 1. count()
long totalItems = cartPrices.stream().count();
System.out.println("Total Items: " + totalItems);
// 2. min() & max() with Optional
Optional<Integer> cheapest = cartPrices.stream().min(Integer::compareTo);
Optional<Integer> mostExpensive = cartPrices.stream().max(Integer::compareTo);
System.out.println("Cheapest: Rs." + cheapest.orElse(0));
System.out.println("Most Expensive: Rs." + mostExpensive.orElse(0));
// 3. reduce(identity, accumulator) -> Calculate Total Sum
int totalPrice = cartPrices.stream().reduce(0, (sum, price) -> sum + price);
System.out.println("Total Cart Value: Rs." + totalPrice);
}
}
Enterprise applications lo database query results ni memory lo group cheyyadaniki Collectors.groupingBy() mariyu Collectors.partitioningBy() vadathamu:
import java.util.*;
import java.util.stream.Collectors;
class Employee {
private String name;
private String department;
private double salary;
public Employee(String name, String dept, double sal) {
this.name = name;
this.department = dept;
this.salary = sal;
}
public String getName() { return name; }
public String getDepartment() { return department; }
public double getSalary() { return salary; }
@Override
public String toString() { return name + " (Rs." + salary + ")"; }
}
public class CollectorsGroupingDemo {
public static void main(String[] args) {
List<Employee> employees = List.of(
new Employee("Ravi", "Engineering", 85000),
new Employee("Sneha", "HR", 60000),
new Employee("Kiran", "Engineering", 110000),
new Employee("Anu", "Marketing", 75000),
new Employee("Bhavna", "HR", 65000)
);
// 1. Collect to Modern Immutable List (Java 16+ Stream.toList())
List<String> engNames = employees.stream()
.filter(e -> e.getDepartment().equals("Engineering"))
.map(Employee::getName)
.toList();
System.out.println("Engineering Team: " + engNames);
// 2. groupingBy: Group employees by Department
Map<String, List<Employee>> byDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
System.out.println("\nEmployees by Department: " + byDept);
// 3. partitioningBy: Split into High Earners (>= 80k) and Regular Earners
Map<Boolean, List<Employee>> highEarners = employees.stream()
.collect(Collectors.partitioningBy(e -> e.getSalary() >= 80000));
System.out.println("\nHigh Earners (>=80k): " + highEarners.get(true));
}
}
โก How Parallel Streams Work Under the Hood
collection.parallelStream() data sequence ni multiple chunks ga divide chesi JVM เฐฏเฑเฐเฑเฐ common ForkJoinPool.commonPool() worker threads meedha parallel ga concurrently process chesthundhi.
โ ๏ธ When to use: Large CPU-intensive datasets (> 100,000 elements) with stateless independent operations.
โ ๏ธ When to avoid: Small datasets (thread coordination overhead makes it slower than sequential), or when operations involve shared mutable state or blocking I/O!
import java.util.stream.LongStream;
public class ParallelStreamDemo {
public static void main(String[] args) {
long limit = 10_000_000L;
// Sequential Stream Sum
long startSeq = System.currentTimeMillis();
long sumSeq = LongStream.rangeClosed(1, limit).sum();
long endSeq = System.currentTimeMillis();
System.out.println("Sequential Sum: " + sumSeq + " (Time: " + (endSeq - startSeq) + " ms)");
// Parallel Multi-Core Stream Sum
long startPar = System.currentTimeMillis();
long sumPar = LongStream.rangeClosed(1, limit).parallel().sum();
long endPar = System.currentTimeMillis();
System.out.println("Parallel Sum: " + sumPar + " (Time: " + (endPar - startPar) + " ms)");
}
}
Run this stream filter and transform pipeline in our online Java compiler:
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = List.of(10, 15, 20, 25, 30);
numbers.stream()
.filter(number -> number % 2 == 0)
.map(number -> number * 2)
.forEach(System.out::println);
}
}