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 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.

## groupingBy and groupingByConcurrent

Java Stream API is the best thing added to Java. It made things much more clear and being declarative in nature, 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 in 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 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"));

**Outoput:**

Even Numbers are : [2, 2, 4, 6, 8, 8, 0] ODD Numbers are : [1, 1, 3, 5, 7, 9]

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 object such as Integer, 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 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, as 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"));

**Output:**

group into sets Even Numbers are : [0, 2, 4, 6, 8] ODD Numbers are : [1, 3, 5, 7, 9]

### 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"));

**Output:**

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

### Get Average of the Values

// lets take 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"));

**Output:**

Group Average of the numbers Even Numbers average: 4.285714285714286 ODD Numbers average: 4.333333333333333

## Nested Grouping

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"));

**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]

## Conlusion

We learned about **groupingBy** and did some various examples on it. It is just the 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 own algorithm for most of the common things. We also have **partitioningBy() **which we will discuss in another post. You can check the whole code describe here on GitHub or Full Project.

Other post related to Stream:

- Iterating over List: Basic to Advance to Stream API
- Stream API: The Hero Without a Cape
- Be More Functional with Java’s Functional Interfaces
- Reduce NullPointerExceptions with Optional in Java 8 & Beyond

See you in next post.

Wandering on the worldwide web and collecting knowledge and learning new things. I came here to share that knowledge with you.