Overview

Implementations of Collector that implement various useful reduction operations, such as accumulating elements into collections, summarizing elements according to various criteria, etc. Here is different ways of java 8 stream group by count with examples like grouping, counting, filtering, summing, averaging, multi-level grouping.

Example 1: Grouping by + Counting

Collectors class provide static factory method groupingBywhich provides a similar kind of functionality as SQL group by clause.

Another useful static method is countingwhich returns a collector accepting an element of T that count number of input elements.

Let’s say we want to group all the elements in a list and count each element occurrences. till Java 7 it was such a lengthy task. Java 8 brings some new capabilities with lambda expression and improved collections API to reduce developer time. Now with Java 8 we can group element of an arraylist and count it’s occurences in just one line of code.

package com.javadeveloperzone;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
 * Created by Lenovo on 30-04-2017.
 */
public class GroupingByCountExample {
    public static void main(String... args) {
        java.util.List<String> strings = Arrays.asList("Zohne", "Redy", "Zohne", "Redy", "Stome");
        java.util.Map<String, Long> nameCount = strings.stream().collect(Collectors.groupingBy(string -> string, Collectors.counting()));
        nameCount.forEach((name, count) -> {
            System.out.println(name + ":" + count);
        });
    }
}

Output

As you can see in below output Zohne and redy comes two times in the list and Stome comes once. We can also compare these names with case insensitivities, remove any punctuation marks etc…

Zohne:2
Stome:1
Redy:2

Example: Grouping by + Counting + Filtering

Let’s think of one step ahead, We always use SQL group by clause with HAVING clause.

Here we have used collectionAndThen static method which takes two arguments. First one is  Collectorand second one is finisher function.

In below example, we will take only those values whose grouping by count greater than 2. So first we will do grouping and than perform filter on result map and then return values. Equivalent SQL server query to this code looks like “SELECT empName from employee groupBy empName having count(empName)>1

java.util.Set<String> grupingThanFilter = allWords.stream().collect(Collectors.collectingAndThen(Collectors
 .groupingBy(Function.identity(), Collectors.counting()),map->{
 map.values().removeIf(l -> l<=2);
 return map.keySet();
 }));
grupingThanFilter.forEach(System.out::println);

Output:

Here as you can see elements which have only one occurrence is removed.

Zohne
Redy

Example 3: Grouping by + summingInt

Let’s say we want to group by the employee by it’s designation and calculate total salary based on the designation.

Collectors class provide another usefull static method  summingIntwhich a collector that produces the sum of an integer value function.

In below example, we have used groupingBy on employee Designation and apply summingInt on employee salary.

java.util.List<Employee> employees = Employee.getEmployee();
       java.util.Map<String, Integer> designationWiseTotalSalary = employees.stream().collect(Collectors
               .groupingBy(Employee::getDesignation, Collectors.summingInt(Employee::getSalary)));
       designationWiseTotalSalary.forEach((k, v) -> {
           System.out.println(k + " : " + v);
       });

Output:

Sr. Developer : 72000
Developer : 113000
CEO : 100000

Example 4: Grouping by + averagingLong

As we discussed earlier, summingInt use to calculate total/sum of an integer, similar way another method called averagingLong and averagingInt is used to calculate average.

Let’s say we want to find the average salary of all the designation of employees using the new Java Collection and lambda API. We can use groupingBy and averagingLong/averagingInt method to achieve the same. Refer below code snippets for more details.

java.util.List<Employee> employees = Employee.getEmployee();
        java.util.Map<String, Double> designationWiseEvgSalary = employees.stream().collect(Collectors
                .groupingBy(Employee::getDesignation, Collectors.averagingLong(Employee::getSalary)));
        designationWiseEvgSalary.forEach((k, v) -> {
            System.out.println(k + " : " + v);
        });

Output:

Sr. Developer : 72000.0
Developer : 28250.0
CEO : 100000.0

Example 5: Multi Level Grouping by + averagingInt

Let’s say we want to find the average salary of all the male and female employee based on his/her designation.

In this type of use cases, we need to group employee first by it’s designation and then group by on gender to achieve multi level grouping by.

Refer below code snippets for more details.

java.util.List<Employee> employees = Employee.getEmployee();
        java.util.Map<String, java.util.Map<String, Double>> designationGroupByAvg = employees.stream()
                                                                                              .collect(Collectors
                                                                                                      .groupingBy(Employee::getDesignation, Collectors
                                                                                                              .groupingBy(Employee::getGender, Collectors
                                                                                                                      .averagingInt(Employee::getSalary))));
        designationGroupByAvg.forEach((designation, values) -> {
            System.out.println("Designation:" + designation);
            values.forEach((gender, avg) -> {
                System.out.println(gender + ":" + avg);
            });
            System.out.println();
        });

Output:

As you can see in below output average salary of all the male and female employee along with his/her designation.

Designation:Sr. Developer
Male:72000.0
Designation:Developer
Female:24000.0
Male:32500.0
Designation:CEO
Male:100000.0

Employee.java

package com.javadeveloperzone;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
/**
 * Created by JavaDeveloperZone on 29-04-2017.
 */
public class Employee  {
    private int no;
    private String name;
    private String designation;
    private String gender;
    private int salary;
    private java.util.Set<String> language = new HashSet<String>();
    public Employee(int no, String name, String designation, String gender,int salary) {
        this.no = no;
        this.name = name;
        this.designation = designation;
        this.gender = gender;
        this.salary  = salary;
    }
    public int getNo() {
        return no;
    }
    public void setNo(int no) {
        this.no = no;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDesignation() {
        return designation;
    }
    public void setDesignation(String designation) {
        this.designation = designation;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    @Override
    public String toString() {
        return this.no + " : " + this.name + " : " + gender + " : " + designation;
    }
    public String addLanguage(String language) {
        this.language.add(language);
        return language;
    }
    public Set<String> getLanguage() {
        return language;
    }
    public static java.util.List<Employee> getEmployee() {
        java.util.List<Employee> employees = new ArrayList<>();
        employees.add(new Employee(1, "Bob", "Developer", "Male",30000));
        employees.add(new Employee(2, "Joy", "Sr. Developer", "Male",72000));
        employees.add(new Employee(3, "John", "CEO", "Male",100000));
        employees.add(new Employee(4, "Bat", "Developer", "Male",35000));
        employees.add(new Employee(5, "Jolly", "Developer", "Female",36000));
        employees.add(new Employee(6, "Bobby", "Developer", "Female",12000));
        return employees;
    }
}

 

 

References

Was this post helpful?

Tags: ,

Leave a Reply

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