Introduction
Java Streams provide a clean and powerful way to process collections of data. Instead of writing long loops, you can use Streams to filter, sort, and group data in a readable and efficient manner. Streams make your code shorter, faster, and easier to maintain. In this article, we will explore how to use Java Streams to filter, sort, and group data, using plain language and practical examples.
What Are Java Streams?
Java Streams (introduced in Java 8) enable developers to operate on data in a functional style. Streams do not store data; they simply process it and return results.
Key Features
Easy data processing
Support for filtering, mapping, reducing, sorting, and grouping
Works well with lists, sets, and maps
Encourages clean and readable code
Example Stream creation
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
Stream<Integer> stream = numbers.stream();
Filtering Data Using Streams
Filtering means selecting only the items that match a given condition.
Example 1: Filter Even Numbers
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
List<Integer> evens = numbers.stream()
.filter(n -> n % 2 == 0)
.toList();
System.out.println(evens); // [2, 4, 6]
Example 2: Filter Employees by Salary
class Employee {
String name;
double salary;
Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
}
List<Employee> employees = List.of(
new Employee("John", 50000),
new Employee("Sara", 75000),
new Employee("Peter", 45000)
);
List<Employee> highEarners = employees.stream()
.filter(e -> e.salary > 50000)
.toList();
Filtering helps extract only relevant data from large datasets.
Sorting Data Using Streams
Sorting means arranging data in ascending or descending order.
Example 1: Sort Numbers
List<Integer> numbers = List.of(5, 3, 9, 1);
List<Integer> sorted = numbers.stream()
.sorted()
.toList();
System.out.println(sorted); // [1, 3, 5, 9]
Example 2: Sort Employees by Salary
List<Employee> sortedBySalary = employees.stream()
.sorted(Comparator.comparingDouble(e -> e.salary))
.toList();
Descending Order
List<Integer> descending = numbers.stream()
.sorted(Comparator.reverseOrder())
.toList();
Sorting with Streams is clean and customizable.
Grouping Data Using Streams
Grouping means organizing data based on shared properties.
Java provides the powerful Collectors.groupingBy method.
Example 1: Group Strings by Length
List<String> names = List.of("Amit", "Raj", "Priya", "Sam");
Map<Integer, List<String>> groupedByLength = names.stream()
.collect(Collectors.groupingBy(String::length));
Example 2: Group Employees by Salary Range
Map<String, List<Employee>> salaryGroups = employees.stream()
.collect(Collectors.groupingBy(e -> {
if (e.salary < 50000) return "Low";
else if (e.salary < 70000) return "Medium";
else return "High";
}));
Grouping helps organize complex data into meaningful categories.
Combining Filtering, Sorting, and Grouping
You can chain multiple Stream operations together.
Example: Filter employees, sort them, then group
Map<String, List<Employee>> result = employees.stream()
.filter(e -> e.salary > 40000)
.sorted(Comparator.comparingDouble(e -> e.salary))
.collect(Collectors.groupingBy(e -> e.salary > 60000 ? "High" : "Medium"));
This demonstrates the true power of Streams.
Real-Life Use Cases of Streams
1. Processing E-Commerce Orders
Filter orders above a certain value, sort by date, and group by city.
2. Customer Analysis in Banking
Filter customers with high balances, sort by account age, group by branch.
3. Student Performance Management
Filter top performers, sort by marks, group by grade.
Java Streams make all of these tasks significantly easier.
Best Practices
Avoid overly complicated Stream chains
Use method references where possible
Keep Streams readable and maintainable
Use parallel streams for CPU-heavy tasks
Summary
Java Streams provide a powerful and user-friendly way to filter, sort, and group data in a functional style. By using clear and chainable operations, developers can write cleaner, faster, and more readable code. Whether you are building applications in India or anywhere else, mastering Streams helps simplify data processing and improves overall code quality.