1. Overview
In this tutorial, We will learn how to perform the groupingby operation in java 8.
If you have worked in the Oracle database, you must have seen the group by the operator in many complex SQL queries.
You will learn the following techniques in this lesson.
- How to java stream group by operation?
- Java stream group by count?
- Java 8 stream group by and sort?
- Java stream group by reduce?
- java stream group by multiple fields?
- group by with custom objects?
In a similar way, we can implement the group by clause from java 8 onwards. Java 8 Stream API is added with the data grouping capabilities as part of Collectors api.
Collectors API is to collect the final data from stream operations.
2. Java 8 Collectors GroupingBy Syntax
groupingBy() method is an overloaded method with three methods.
This method returns a new Collector implementation with the given values.
public static <T,K> Collector<T,?,Map<K,List<T>>> groupingBy(Function<? super T,? extends K> classifier) public static <T,K,A,D> Collector<T,?,Map<K,D>> groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream) public static <T,K,D,A,M extends Map<K,D>> Collector<T,?,M> groupingBy(Function<? super T,? extends K> classifier, Supplier<M> mapFactory, Collector<? super T,A,D> downstream)
Note:
Remember always group by operations returns a Map with the actual key and aggregated result as value.
3. Java 8 GroupingBy - Group by count
First, let us understand the simple group by operation to find the number of occurrences of each string from List.
package com.javaprogramto.java8.collectors.groupby; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; public class GroupingByCount { public static void main(String[] args) { // Creating List and adding duplicate values. List<String> strings = new ArrayList<>(); strings.add("Hello"); strings.add("Ram"); strings.add("Hello"); strings.add("Sam"); strings.add("Hello"); strings.add("Yam"); strings.add("Hello"); strings.add("Raj"); strings.add("Hello"); strings.add("Raj"); // Grouping by based on the count Map<String, Long> countMap = strings.stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); // printing the count of each string using groupingBy() System.out.println("Count : "+countMap); } }
Output:
Count : {Yam=1, Hello=5, Raj=2, Sam=1, Ram=1}
In the input list, the word Hello is repeated 5 times, Raj is for 2 times and reaming are for 1 time.
Group by operation is simplified using the new java 8 collectors api.
4. Java 8 - Grouping By and Sort
Next, Look at another example to sort the count operation.
package com.javaprogramto.java8.collectors.groupby; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.function.Function; import java.util.stream.Collectors; public class GroupingByCountSort { public static void main(String[] args) { // Creating List and adding duplicate values. List<String> strings = new ArrayList<>(); strings.add("Hello"); strings.add("Ram"); strings.add("Hello"); strings.add("Sam"); strings.add("Hello"); strings.add("Yam"); strings.add("Hello"); strings.add("Raj"); strings.add("Hello"); strings.add("Raj"); // Grouping by based on the count Map<String, Long> countMap = strings.stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); Map<String, Long> groupBySorted = countMap.entrySet().stream().sorted(Entry.comparingByValue()) .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(), (e1, e2) -> e2, LinkedHashMap::new)); // printing the count of each string and sorted System.out.println("Count sorted : " + groupBySorted); } }
Output:
Count sorted : {Yam=1, Sam=1, Ram=1, Raj=2, Hello=5}
The output map is sorted by value in ascending order.
5. Java 8 Group by Sort Descending Order
// Descending Order // Grouping by based on the count Map<String, Long> countMap2 = strings.stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); Map<String, Long> finalMapDescendingOrder = new LinkedHashMap<>(); // Sort a map and add to finalMap countMap2.entrySet().stream().sorted(Map.Entry.<String, Long>comparingByValue().reversed()) .forEachOrdered(e -> finalMapDescendingOrder.put(e.getKey(), e.getValue())); System.out.println("Descending order sorted - " + finalMapDescendingOrder);
Output:
Descending order sorted - {Hello=5, Raj=2, Yam=1, Sam=1, Ram=1}
6. GroupingBy with List of Custom Objects
Let us create a custom class called Stock with name, quantity and price properties.
Create objects for Stock class and add them to the List.
Next, perform group by on stock name and sum quantity.
Stock.java
package com.javaprogramto.java8.collectors.groupby; public class Stock { private String name; private int quantity; private double price; public Stock(String name, int quantity) { this.name = name; this.quantity = quantity; } public Stock(String name, int quantity, double price) { super(); this.name = name; this.quantity = quantity; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } }
GroupingBy by Sum:
package com.javaprogramto.java8.collectors.groupby; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class GroupingByCountObjects { public static void main(String[] args) { // Creating List and adding duplicate values. List<Stock> stocks = new ArrayList<>(); stocks.add(new Stock("JP Morgan", 10)); stocks.add(new Stock("ICICI", 10)); stocks.add(new Stock("HDFC", 10)); stocks.add(new Stock("ICICI", 10)); stocks.add(new Stock("JP Morgan", 10)); stocks.add(new Stock("JP Morgan", 10)); // group by - stock name + sum(quanity) Map<String, Integer> noOfStocksByName = stocks.stream() .collect(Collectors.groupingBy(Stock::getName, Collectors.summingInt(Stock::getQuantity))); // printing the count of each string. System.out.println("No of stocks by stock name : " + noOfStocksByName); } }
Output:
No of stocks by stock name : {ICICI=20, HDFC=10, JP Morgan=30}
7. GroupingBy by Multiple Fields
Next, apply the group by on multiple fields of Stock Name and Quantity. If these two fields are equal then get the count for no of stock objects.
package com.javaprogramto.java8.collectors.groupby; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class GroupingByMultipleFields { public static void main(String[] args) { // Creating List and adding duplicate values. List<Stock> stocks = new ArrayList<>(); stocks.add(new Stock("JP Morgan", 10, 100)); stocks.add(new Stock("ICICI", 20, 100)); stocks.add(new Stock("HDFC", 30, 300)); stocks.add(new Stock("ICICI", 20, 200)); stocks.add(new Stock("JP Morgan", 10, 100)); stocks.add(new Stock("JP Morgan", 10, 100)); // group by - stock name + quanity Map<String, Map<Integer, Long>> noOfStocksByName = stocks.stream() .collect(Collectors.groupingBy(Stock::getName, Collectors.groupingBy(Stock::getQuantity, Collectors.counting()))); // printing the count of each string. System.out.println("Group by on multiple properties" + noOfStocksByName); } }
Output:
Group by on multiple properties{ICICI={20=2}, HDFC={30=1}, JP Morgan={10=3}}
8. Conclusion
In this article, We have seen how to use group by function in java 8 collections.
Examples are shown to get the count, sort, sum on custom objects, group by on multiple fields.
And also we can modify the return Map value type, Getting the average, sum, minimum, maximum and Summary values from grouped results.
No comments:
Post a Comment
Please do not add any spam links in the comments section.