Home Java How to use groupingBy Collector in Java Streams

How to use groupingBy Collector in Java Streams

Published: Last Updated on 0 comment 3.7k views

Hey, Tea lovers! Today we will talk about the groupingBy Collector method of Java Stream API. Yes, it is similar to GROUP BY of SQL since it groups and collects the objects based on a given condition or value. In case you want to get familiar with the Stream API, I recommend you to read the post “Be More Functional with Java’s Functional Interfaces” and “Stream API: The Hero Without a Cape“. These will help you understand the post and might refresh your memory if you already know. Prepare your tea then, to sip and code.

I have also written a post on How to Use partitioningBy Collector in Java Stream API

You can follow me on social media via @coderstea on TwitterLinkedinFacebook, or Instagram. We also share high-quality videos about programming on our YouTube channel. You can also publish your post on CodersTea, just share your thought on Contact Us or let us know in the comments.

groupingBy and groupingByConcurrent

Java Stream API is the best thing added to Java. It made things much more clear and being declarative, made it more readable. One of the Terminal functions of the Stream is groupingBy. As I said, it works kind of similar to the GROUP BY in SQL, except it works on Stream. It collects the object V, the one which is available now in the pipeline, into the Map<K, List<V>>, where K is the value on which the V is grouped. So the objects which have or generate the same key get added to the list of the same key. The groupingBy is overloaded so you can modify the return Map instance however you like. Map<K, List<V>> is the simplest one.

groupingByConcurrent is the same as groupingBy, however, it is thread-safe.

List<Integer> list = Arrays.asList(1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 8, 9, 0); // Simplest groupingBy System.out.println("Simplest groupingBy"); Map< String, List< Integer > > oddEvenNumbers = list.stream() //grouped with EVEN or ODD .collect(groupingBy(n -> n % 2 == 0 ? "EVEN" : "ODD")); System.out.println("Even Numbers are : " + oddEvenNumbers.get("EVEN")); System.out.println("ODD Numbers are : " + oddEvenNumbers.get("ODD"));
Code language: PHP (php)

Output:

Even Numbers are : [2, 2, 4, 6, 8, 8, 0] ODD Numbers are : [1, 1, 3, 5, 7, 9]
Code language: CSS (css)

In the above code, I have grouped based on the EVEN and ODD value. As this method executes it generates either EVEN or ODD as the key for the numbers and gets added to the respective key’s List. I have used String here, but you can use any type of objects such as an Integer, or some custom class of yours.

Now, what if We don’t want to just create a List instead of some different things? Like a Set, or we want a summation of those numbers. Well, you can do so using the overloaded groupingBy.

Be a groupingBy Stream API Pro

groupingBy also takes another argument which is another Collector. You can modify the value in the final map to any other value rather than a List.

I will go through some different examples. I am only using List<Integer>, defined in the first code block, to keep things simpler.

Group into Set

// group into sets System.out.println("group into sets"); Map<String, Set<Integer>> oddEvenWithSet = list.stream() .collect(groupingBy(n -> n % 2 == 0 ? "EVEN" : "ODD", toSet())); System.out.println("Even Numbers are : " + oddEvenWithSet.get("EVEN")); System.out.println("ODD Numbers are : " + oddEvenWithSet.get("ODD"));
Code language: JavaScript (javascript)

Output:

group into sets Even Numbers are : [0, 2, 4, 6, 8] ODD Numbers are : [1, 3, 5, 7, 9]
Code language: CSS (css)

Sum the Values

// sum the numbers System.out.println("sum the numbers "); Map<String, Integer> sumOddOrEvenSquares = list.stream() // lets convert to square .map(n -> n * n) //grouped with EVEN or ODD .collect(groupingBy(n -> n % 2 == 0 ? "EVEN" : "ODD" , Collectors.summingInt(Integer::intValue) )); System.out.println("Even Numbers squared sum: " + sumOddOrEvenSquares.get("EVEN")); System.out.println("ODD Numbers squared sum: " + sumOddOrEvenSquares.get("ODD"));
Code language: JavaScript (javascript)

Output:

sum the numbers Even Numbers squared sum: 188 ODD Numbers squared sum: 166

Get the Average of the Values

//let's take an average System.out.println("Group Average of the numbers"); Map<String, Double> averageOfOddEven = list.stream() //grouped with EVEN or ODD .collect(groupingBy(n -> n % 2 == 0 ? "EVEN" : "ODD" , Collectors.averagingInt(Integer::intValue) )); System.out.println("Even Numbers average: " + averageOfOddEven.get("EVEN")); System.out.println("ODD Numbers average: " + averageOfOddEven.get("ODD"));
Code language: JavaScript (javascript)

Output:

Group Average of the numbers Even Numbers average: 4.285714285714286 ODD Numbers average: 4.333333333333333
Code language: CSS (css)

Nested Grouping with groupingBy

Grouped values can be grouped again if we pass the groupingBy collector in the second argument.

Here, we have grouped the numbers based on Odd and Even values in the first groupingBy. After that, we are regrouping based on if the number is greater and less than or equal to 5.

// group again System.out.println("Group again with some greater than 5"); Map<String, Map<String, Set<Integer>>> oddEvenAndCompareTo5 = list.stream() .collect(groupingBy(n -> n % 2 == 0 ? "EVEN" : "ODD", groupingBy(n -> n > 5 ? "GT5" : "LT5", toSet()) )); Map<String, Set<Integer>> evenNumbers = oddEvenAndCompareTo5.get("EVEN"); Map<String, Set<Integer>> oddNumbers = oddEvenAndCompareTo5.get("ODD"); System.out.println("Even numbers greater than 5: " + evenNumbers.get("GT5")); System.out.println("Odd numbers greater than 5: " + oddNumbers.get("GT5")); System.out.println("Even numbers Less than or equal to 5: " + evenNumbers.get("LT5")); System.out.println("Odd numbers Less than or equal to 5: " + oddNumbers.get("LT5"));
Code language: JavaScript (javascript)

Output:

Group again with some greater than 5 Even numbers greater than 5: [6, 8] Odd numbers greater than 5: [7, 9] Even numbers Less than or equal to 5: [0, 2, 4] Odd numbers Less than or equal to 5: [1, 3, 5]
Code language: CSS (css)

Conclusion

We learned about groupingBy and did some various examples of it. It is just basic, you can use it according to your requirement. groupingByConcurrent is the same as groupingBy but can be used in parallel Stream without any side effects and uses ConcurrentMap.

The Stream API is filled with so many functions you don’t need to create your algorithm for most of the common things. We also have partitioningBy() which we will discuss in another post. You can check the whole code described here on GitHub or Full Project.

Other posts related to Stream:

See you in the next post. HAKUNA MATATA!!!

You can follow me on social media via @coderstea on TwitterLinkedinFacebook, or Instagram. We also share high-quality videos about programming on our YouTube channel. You can also publish your post on CodersTea, just share your thought on Contact Us or let us know in the comments.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Newsletter

Subscribe my Newsletter for new blog posts, tips & new photos. Let's stay updated!

@2022 All Right Reserved. Designed and Developed by CodersTea

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More