Core Java

Java 8 groupingBy Collector


GroupingBy Collectors introduced in Java 8 provides us a functionality much similar to using GROUP BY clause in a SQL statement. It helps us group objects based on certain property, returning a Map as an outcome.

In this article, we’ll look at various example usages of the groupingBy collector in Java 8. To follow along with this tutorial, we assume you have a basic understanding of Java 8 Stream API and Java 8 Stream Collectors.

GroupingBy Collector Signatures:

Let’s look at available overloaded method signatures for groupingBy():

Here, we have:

  1. classifier: Classification function used for grouping the elements
  2. downstream: Collector used to perform further reduction over the values associated with a given key
  3. mapFactory: Supplier factory function to be used to create the output Map

Example Setup:

Let’s assume we have a Student object:

And we maintain a List<Student>:

In the examples that follow, we’ll open our stream over this List of students.

Grouping By A Single Field:

Let’s first try out the easiest groupingBy() method which only accepts a classifier function. The value returned by our classifier will form a key element in the resulting Map:

If we print out studentsByCountry to the console, we’ll get:

Collecting Values In A Set:

By default, all the values being mapped to a key are collected into a List<T>. What if we want them to be stored in a Set<T>?

We can achieve it by using the second overloaded method:

Getting Count Of Grouped Items:

As we now know, the second argument of groupingBy() is another Collector, so it’s pretty easy to get a count map:

Averaging the Grouped Result:

What if we want to find the average student age of each country? Our code implementation would look like:

Finding Max/Min Element In Grouped Result:

Collectors.maxBy()/minBy() help us find the maximum/minimum values among the various items in each group:

studentWithMaxAgePerCountry is a Map which holds the student with maximum age corresponding to each country. It’s important to note that an Optional<Student> is returned as a value, considering we could have an empty List as well.

On the similar lines, we can use minBy() Collector as well.

Mapping Grouped Results:

Collectors.mapping() can also be used along with groupingBy() method. Suppose we intend to find max age per country. To achieve so, we’ll write:

mapping(mapper, downstream) collector transforms every element passed to it using a mapper function passed to it and then passes that transformed element to the downstream collector.

Grouping By Multiple Fields:

Grouping by using multiple fields grouped as a key is a more involved operation. Let’s try to group our students by country as well as age:

If we print the above Map, we’ll have:

Here, we have first grouped by country name and then we have further grouped them by age.

Defining Output Map Type:

It’s also possible for us to define the type of Map we would like to be produced as an outcome:


In this tutorial, we learned how to use Java 8 Collector – groupingBy to group our elements based on different attributes.

Be the First to comment.

Leave a Comment

Your email address will not be published. Required fields are marked *