Main Tutorials

Java 8 – Stream Collectors groupingBy examples

In this article, we will show you how to use Java 8 Stream Collectors to group by, count, sum and sort a List.

1. Group By, Count and Sort

1.1 Group by a List and display the total count of it.

Java8Example1.java

package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Java8Example1 {

    public static void main(String[] args) {
        
        //3 apple, 2 banana, others 1
        List<String> items =
                Arrays.asList("apple", "apple", "banana",
                        "apple", "orange", "banana", "papaya");

        Map<String, Long> result =
                items.stream().collect(
                        Collectors.groupingBy(
                                Function.identity(), Collectors.counting()
                        )
                );

        System.out.println(result);


    }
}

output

{
	papaya=1, orange=1, banana=2, apple=3
}

1.2 Add sorting.

Java8Example2.java

package com.mkyong.java8;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Java8Example2 {

    public static void main(String[] args) {

        //3 apple, 2 banana, others 1
        List<String> items =
                Arrays.asList("apple", "apple", "banana",
                        "apple", "orange", "banana", "papaya");

        Map<String, Long> result =
                items.stream().collect(
                        Collectors.groupingBy(
                                Function.identity(), Collectors.counting()
                        )
                );

        Map<String, Long> finalMap = new LinkedHashMap<>();

        //Sort a map and add to finalMap
        result.entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue()
                        .reversed()).forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));

        System.out.println(finalMap);


    }
}

output

{
	apple=3, banana=2, papaya=1, orange=1
}

2. List Objects

Examples to ‘group by’ a list of user defined Objects.

2.1 A Pojo.

Item.java

package com.mkyong.java8;

import java.math.BigDecimal;

public class Item {

    private String name;
    private int qty;
    private BigDecimal price;

    //constructors, getter/setters 
}

2.2 Group by the name + Count or Sum the Qty.

Java8Examples3.java

package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Java8Examples3 {

    public static void main(String[] args) {

        //3 apple, 2 banana, others 1
        List<Item> items = Arrays.asList(
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 20, new BigDecimal("19.99")),
                new Item("orang", 10, new BigDecimal("29.99")),
                new Item("watermelon", 10, new BigDecimal("29.99")),
                new Item("papaya", 20, new BigDecimal("9.99")),
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 10, new BigDecimal("19.99")),
                new Item("apple", 20, new BigDecimal("9.99"))
        );

        Map<String, Long> counting = items.stream().collect(
                Collectors.groupingBy(Item::getName, Collectors.counting()));

        System.out.println(counting);

        Map<String, Integer> sum = items.stream().collect(
                Collectors.groupingBy(Item::getName, Collectors.summingInt(Item::getQty)));

        System.out.println(sum);

    }
}

output

//Group by + Count
{
	papaya=1, banana=2, apple=3, orang=1, watermelon=1
}

//Group by + Sum qty
{
	papaya=20, banana=30, apple=40, orang=10, watermelon=10
}

2.2 Group by Price – Collectors.groupingBy and Collectors.mapping example.

Java8Examples4.java

package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class Java8Examples4 {

    public static void main(String[] args) {

        //3 apple, 2 banana, others 1
        List<Item> items = Arrays.asList(
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 20, new BigDecimal("19.99")),
                new Item("orang", 10, new BigDecimal("29.99")),
                new Item("watermelon", 10, new BigDecimal("29.99")),
                new Item("papaya", 20, new BigDecimal("9.99")),
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 10, new BigDecimal("19.99")),
                new Item("apple", 20, new BigDecimal("9.99"))
                );

		//group by price
        Map<BigDecimal, List<Item>> groupByPriceMap = 
			items.stream().collect(Collectors.groupingBy(Item::getPrice));

        System.out.println(groupByPriceMap);

		// group by price, uses 'mapping' to convert List<Item> to Set<String>
        Map<BigDecimal, Set<String>> result =
                items.stream().collect(
                        Collectors.groupingBy(Item::getPrice,
                                Collectors.mapping(Item::getName, Collectors.toSet())
                        )
                );

        System.out.println(result);

    }
}

output

{
	19.99=[
			Item{name='banana', qty=20, price=19.99}, 
			Item{name='banana', qty=10, price=19.99}
		], 
	29.99=[
			Item{name='orang', qty=10, price=29.99}, 
			Item{name='watermelon', qty=10, price=29.99}
		], 
	9.99=[
			Item{name='apple', qty=10, price=9.99}, 
			Item{name='papaya', qty=20, price=9.99}, 
			Item{name='apple', qty=10, price=9.99}, 
			Item{name='apple', qty=20, price=9.99}
		]
}

//group by + mapping to Set
{
	19.99=[banana], 
	29.99=[orang, watermelon], 
	9.99=[papaya, apple]
}

References

  1. Java 8 Stream Collectors JavaDoc
  2. Java – How to sort a Map
  3. Stackoverflow – Sort a Map by values (Java)

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
36 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Valentino
6 years ago

Greate information!!!

Carol
6 years ago

Thanks, good examples

GOWRI SANKAR
6 years ago

Nice set of examples. Thank you!

sandip soliya
4 years ago
Reply to  GOWRI SANKAR

good examples for beginners

Miguel Moreno
7 years ago

What about doing the same example, but grouping by item name and summing the BigDecimal amounts?

Anonymous
4 years ago
Reply to  Miguel Moreno

Map<String, Double> result = items.stream()
.collect(Collectors.groupingBy(Item::getName, Collectors.summingDouble(i -> i.getPrice().doubleValue())));

Ravi
2 years ago
Reply to  Anonymous

can you give the full code please

rpalvair
7 years ago

Good 😉

Jason
1 year ago

Why is a LinkedHashMap being used for the sort?

 Map<String, Long> finalMap = new LinkedHashMap<>();
Jason
1 year ago
Reply to  Jason

Ah it’s because a LHM preserves insertion order.

kapil kumar yadav
1 year ago

Good information

YuryS
1 year ago

Good solutions! Thanks!

Alex
2 years ago

loved it! thanks

Pradnya
2 years ago

Hello,
I am trying to learn functional programming in java. Below is my code

LambdaExperiments.java

package com.practice.functionalprogramming;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import java.util.stream.Stream;
import java.util.stream.Collectors;

class Employee {

private int salary;
private String name;
private int age;
public Employee(int salary, String name, int age) {
super();
this.salary = salary;
this.name = name;
this.age = age;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return “Employee [salary=” + salary + “, name=” + name + “, age=” + age
+ “]”;
}
}
public class LambdaExperiments {
public static void main(String[] args) {
Employee e1 = new Employee(1000, “Emp1”, 23);
Employee e2 = new Employee(500, “Emp2”, 24);
Employee e3 = new Employee(10000, “Emp3”, 27);
Employee e4 = new Employee(100, “Emp4”, 20);
Employee e5 = new Employee(15000, “Emp5”, 21);
Employee e6 = new Employee(10050, “Emp6”, 30);

List<Employee> listEmp = new ArrayList<Employee>();
listEmp.add(e1);listEmp.add(e2);
listEmp.add(e3);listEmp.add(e4);
listEmp.add(e5);listEmp.add(e6);

Stream<Employee> stream = listEmp.stream();
int sum = stream.collect(Collectors.summingInt(Employee::getSalary));

}
}

However I am getting compilation error

Exception in thread “main” java.lang.Error: Unresolved compilation problems: 
Employee cannot be resolved to a variable
Syntax error on tokens, delete these tokens

I have recently updated from jdk 6 to 8.Please provide some pointers!

Sam
2 years ago
Reply to  Pradnya

if a variable say unresolved , you need to import that POJO in main class

Kunal
2 years ago

Exceptionally well explained and demonstratd

Sefirosu
3 years ago

In exp: “2.2 Group by Price”
The output: “19.99” -> “29.99” -> “9.99”
As you can see, the list has been added like “9.99” -> “19.99” -> “29.99”
How to arrange output list like input?

Jeet
4 years ago

Can I achive like – https://stackoverflow.com/questions/59876881/transform-query-results-into-different-format using anything above ? Would you please asssssist me????

Vlad
4 years ago

Not interesting. Very easy simple tasks. Make at least sum of BigDecimals. 🙁

Deepak
11 months ago
Reply to  Vlad

 Map<String, BigDecimal> sumP = items.stream().collect(
       Collectors.groupingBy(Item::getName, Collectors.reducing(BigDecimal.ZERO ,
           (Item a)-> a.getPrice() , (a, b) -> a.add(b))));

Ajith
4 years ago

In the example 2.1,

Map counting = items.stream().collect(
Collectors.groupingBy(Item::getName, Collectors.counting()));

//In this above line (Item::getName) ,how its working because non static method called directly using Class Name

Amirhossein
4 years ago

great, these examples saved my time. thanx.

RAJA SEKHAR CHITTIPROLU
4 years ago

HI I have a list with 24 elements and I want to group them 4 individual lists with each list having 6 elements. how can i do it.

Ramanjaneyulu
4 years ago

Hi Raja sekhar,
The below is the logic:
List list = new ArrayList();

list.add(“abc”);
list.add(“aaa”);
list.add(“bbb”);
list.add(“ccc”);
list.add(“ddd”);
list.add(“eee”);
list.add(“fff”);
list.add(“ggg”);

List list1 = list.subList(0, 2);
List list2 = list.subList(2, 4);
List list3 = list.subList(4, 6);
List list4 = list.subList(6, 8);

System.out.println(list1);
System.out.println(list2);
System.out.println(list3);
System.out.println(list4);

Mary
4 years ago

Hi, is very nice information, thanks for sharing. I would like to know how could be the best way to sort a map by the order of insertion of values from ArrayList? For example:

Here the list with the correct order of values
List list = new ArrayList();
list.add(“DELETE”);
list.add(“ADD”);
list.add(“CHANGE”);

and the insertion order map:
Map m = new HashMap();
m.put(“CHANGE”,”Attr1″);
m.put(“ADD”,”Attr2″);
m.put(“DELETE”,”Attr3″);
m.put(“CHANGE”,”Attr4″);

The expected result is as follow:
DELETE=Attr3,ADD=Attr2,CHANGE=Attr4

How can I apply the sort in the map taking as source the values of the list?

I hope be clear in my question. Thanks a lot

sandip soliya
4 years ago

Very nice expatiation by examples.. it help well for beginners..Thank you

Andrea
5 years ago

the last example is grouped by price, but is not sorted by increasing price, but literal. I have e three level grouped map, and i need to sort the middle level which has the key as float. How can i do it?

miri
5 years ago

Thank you!
do you have the full examples in Github?

shameem
6 years ago

thanks, very helpfull

Eshkere
6 years ago

1.2 Should avoid using mutable variables like finalMap.

Venky
6 years ago

Very good explanation..Thank you

Rubin Roy
6 years ago

Is there a way to check grouping based on a set.
Eg. If there is a Set with Apple, banana, Orange, Papaya and if the ArrayList doesn’t have an apple is there a way to use Stream and grouping to get result like below

//Group by + Count
{
papaya=1, banana=2, apple=0, orange=1, watermelon=1//
}

Chinmay C
7 years ago

Thanks!

murthy gandikota
7 years ago

In the example 1.2 above, the collection has to be sorted by key as well:

//Sort a map and add to finalMap
result.entrySet().stream()
.sorted(Map.Entry.comparingByValue()
.reversed()).sorted(Map.Entry.comparingByKey()).
forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));

The resulting output is
{apple=3, banana=2, orange=1, papaya=1}

Thanks

oleg gavryliv
5 years ago

Why do we need forEachOrdered here? Cause we use sequential stream.