📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.
🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.
▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube
If you’ve worked with Java Streams, chances are you’ve heard of Collectors.groupingBy()
. It’s one of the most powerful features for aggregating and organizing data — especially when you’re dealing with large datasets in real-world applications.
In this guide, you’ll learn:
- ✅ What
groupingBy()
is and how it works - 📊 How to use it in real-world scenarios
- 🔄 Advanced tricks like nested grouping and downstream collectors
- ⚖️ When to use
groupingBy()
vspartitioningBy()
📦 What Is Collectors.groupingBy()
?
Collectors.groupingBy()
is a collector used with Java Streams to group elements of a collection by a classification function, returning a Map<K, List<T>>
by default.
🔤 Basic Syntax:
Map<K, List<T>> map = stream.collect(Collectors.groupingBy(classifier));
🧱 Domain Model for Examples
We’ll use the following classes for our examples:
record Product(String name, String category, double price) {}
Sample data:
List<Product> products = List.of(
new Product("iPhone", "Electronics", 90000),
new Product("TV", "Electronics", 40000),
new Product("Shirt", "Clothing", 1500),
new Product("Jeans", "Clothing", 2000),
new Product("Laptop", "Electronics", 120000)
);
✅ 1. Group Products by Category
Map<String, List<Product>> groupedByCategory = products.stream()
.collect(Collectors.groupingBy(Product::category));
groupedByCategory.forEach((category, items) -> {
System.out.println(category + ": " + items);
});
🧾 Output:
Electronics: [iPhone, TV, Laptop]
Clothing: [Shirt, Jeans]
✅ 2. Group and Count Products per Category
Use a downstream collector to count grouped items:
Map<String, Long> countByCategory = products.stream()
.collect(Collectors.groupingBy(
Product::category,
Collectors.counting()
));
System.out.println(countByCategory);
🧾 Output:
Electronics: 3
Clothing: 2
✅ 3. Group by Category and Sum Prices
Map<String, Double> totalByCategory = products.stream()
.collect(Collectors.groupingBy(
Product::category,
Collectors.summingDouble(Product::price)
));
System.out.println(totalByCategory);
🧾 Output:
Electronics: 250000.0
Clothing: 3500.0
✅ 4. Nested Grouping: Category → Price Range
Let’s group products first by category, then by price range.
Map<String, Map<String, List<Product>>> nestedGrouping = products.stream()
.collect(Collectors.groupingBy(
Product::category,
Collectors.groupingBy(p -> {
if (p.price() > 50000) return "Expensive";
else return "Affordable";
})
));
System.out.println(nestedGrouping);
🧾 Output:
Electronics: {
Expensive=[iPhone, Laptop],
Affordable=[TV]
}
Clothing: {
Affordable=[Shirt, Jeans]
}
✅ 5. Grouping with Custom Collection (Set Instead of List)
Map<String, Set<String>> productNamesByCategory = products.stream()
.collect(Collectors.groupingBy(
Product::category,
Collectors.mapping(Product::name, Collectors.toSet())
));
System.out.println(productNamesByCategory);
🧾 Output:
Electronics: [TV, Laptop, iPhone]
Clothing: [Shirt, Jeans]
✅ 6. Top Product per Category (Max by Price)
Map<String, Optional<Product>> mostExpensiveProduct = products.stream()
.collect(Collectors.groupingBy(
Product::category,
Collectors.maxBy(Comparator.comparingDouble(Product::price))
));
System.out.println(mostExpensiveProduct);
🧾 Output:
Electronics: Laptop
Clothing: Jeans
✅ 7. Custom Key Grouping: First Letter of Product Name
Map<Character, List<Product>> byFirstLetter = products.stream()
.collect(Collectors.groupingBy(p -> p.name().charAt(0)));
System.out.println(byFirstLetter);
🧾 Output:
i: [iPhone]
T: [TV]
S: [Shirt]
J: [Jeans]
L: [Laptop]
⚖️ groupingBy()
vs partitioningBy()
Feature | groupingBy() |
partitioningBy() |
---|---|---|
Keys | Multiple (any type) | Only two groups: true and false |
Use case | Group by any field/classifier | Split data based on a boolean test |
Return type | Map<K, List<T>> |
Map<Boolean, List<T>> |
🧪 Example:
Map<Boolean, List<Product>> expensivePartition = products.stream()
.collect(Collectors.partitioningBy(p -> p.price() > 50000));
🧠 Final Thoughts
The Collectors.groupingBy()
method is one of the most versatile tools in the Java Stream API. Whether you need to:
- Group by one or more fields
- Count, sum, or aggregate
- Apply nested groupings or transformations
Start with basic groupings and then move into nested and custom downstream collectors as your use cases grow.
Comments
Post a Comment
Leave Comment