JB Header
Java 8 How to use Collectors summarizingInt, summarizingLong, summarizingDouble with examples
This tutorial explains how to use the predefined summarizing collectors returned by Collectors.summarizingInt(), Collectors.summarizingLong() and Collectors.summarizingDouble() methods with examples. It first explains the method definitions of these 3 methods, with insights into the structure of the Summary Statistics classes which encapsulate the calculated statistics returned by the collectors. It then shows how to use the summarizing collectors with a Java 8 code example, along with detailed explanation of the code. Definition of summarizing collectors The 3 summarizing collectors have almost identical signatures except for the type of data(int/ long/ double) they handle -
public static <T> Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper)

public static <T> Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper)

public static <T> Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)

Where,
     - input for all 3 collectors is a FunctionClick to Read Tutorial on Function interface which extracts an int/long/double type of value as it works on the objects of the stream.(Note - The definitions use the predefined ToIntFunction/ ToLongFunction/ ToDoubleFunction interfaces as the input parameter types, instead of generic Function, as the function descriptorsClick to Read tutorial on Java 8 Function Descriptors of these interfaces match the requirements of summarizing collectors)
     - output is a Collector with finisherClick to Read tutorial on 4 components of Collectors incl. 'finisher'(return type) of type IntSummaryStatistics/ LongSummaryStatistics/ DoubleSummaryStatistics.
How the summarizing collector works Given a stream of objects, summarizing collectors provided by the methods Collectors.summarizingInt(), Collectors.summarizingLong() and Collectors.summarizingDouble() calculate a bunch of statistical calculations for a given numerical value derived from the stream's objects, and return these statistics encapsulated inside objects of specially defined statistical classes for this purpose viz. IntSummaryStatistics, LongSummaryStatistics & DoubleSummaryStatistics.

The statistical attributes encapsulated by the summary statistics classes are -
  • count of numeric value derived
  • sum of values
  • minimum value
  • maximum value
  • average of all values
Bold & underlined words in the list above indicate the attribute name in summary statistics classes. These attributes have convenient individual getters(getCount(), getSum()...) to retrieve the computed statistical values individually as per your requirement.

ToIntFunction, ToLongFunction, and ToDoubleFunctions, defined as the input parameter for summarizing methods, are predefined functional interfaces in java.util.functionClick to Read Tutorial on Overview of Java 8’s new java.util.function package package. These interfaces convert objects to their primitive equivalent value in int, long and double types, and their use in the definition allows for precisely specifying the 'type' of Function expected for the summarizing methods instead of the more general Function<T,R> definition. Example showing usage of collectors - summarizingInt, summarizingLong, summarizingDouble Problem Description: Given a stream of Employee objects, we want to -
  1. Find the summary of statistics of employee age which is of type int.
  2. Find the summary of statistics of employee leaves which is of type long.
  3. Find the summary of statistics of employee salary which is of type double.
Solution code for the above problem is -
Java 8 Code Example for summarizingInt, summarizingLong, summarizingDouble
package com.javabrahman.java8.collector;

import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.DoubleSummaryStatistics;
import java.util.stream.Collectors;
import com.javabrahman.java8.Employee;
public class SummarizingCollectors {
  static List<Employee> employeeList
      = Arrays.asList(new Employee("Tom Jones", 45, 15000.00,190),
      new Employee("Tom Jones", 45, 7000.00,220),
      new Employee("Ethan Hardy", 65, 8000.00,1008),
      new Employee("Nancy Smith", 22, 10000.00,5),
      new Employee("Deborah Sprightly", 29, 9000.00,45));

  public static void main(String[] args) {
    //Using Collectors.summarizingInt()
    IntSummaryStatistics intSummaryStatistics = employeeList
        .stream()
        .collect(Collectors.summarizingInt(Employee::getAge));
    System.out.println("IntSummaryStatistics for age: " + intSummaryStatistics);

    //Using Collectors.summarizingLong()
    LongSummaryStatistics longSummaryStatistics = employeeList
        .stream()
        .collect(Collectors.summarizingLong(Employee::getLeaves));
    System.out.println("LongSummaryStatistics for leaves: " + longSummaryStatistics);

    //Using Collectors.summarizingDouble()
    DoubleSummaryStatistics doubleSummaryStatistics = employeeList
        .stream()
        .collect(Collectors.summarizingDouble(Employee::getSalary));
    System.out.println("DoubleSummaryStatistics for salary: " + doubleSummaryStatistics);
  }
}
//Employee.java POJO class
package com.javabrahman.java8;
import java.text.DecimalFormat;
public class Employee {
  private String name;
  private Integer age;
  private Double salary;
  private long leaves;

  public Employee(String name, Integer age, Double salary, long leaves) {
    this.name = name;
    this.age = age;
    this.salary = salary;
    this.leaves = leaves;
  }

  //Standard getters & setters for name, age, salary and leaves go here

  //Standard equals() & hashcode() methods go here
}
 OUTPUT of the above code
IntSummaryStatistics for age: IntSummaryStatistics{count=5, sum=206, min=22, average=41.200000, max=65}
LongSummaryStatistics for leaves: LongSummaryStatistics{count=5, sum=1468, min=5, average=293.600000, max=1008}
DoubleSummaryStatistics for salary: DoubleSummaryStatistics{count=5, sum=49000.000000, min=7000.000000, average=9800.000000, max=15000.000000}
Explanation of the code
  • SummarizingCollectors class contains a static list of Employee objects - employeeList.
  • A stream of Employee objects is created using List.stream() method.
  • Stream of employees is pipelinedClick to Read Tutorial explaining Concept of Pipelines in Computing to the collect() terminal operationClick to Read Tutorial explaining intermediate & terminal Stream operations.
  • The code for 3 summarizing collectors is same until this point. From here it proceeds slightly different for the three -
    • Collectors.summarizingInt Collector
      • Collector returned by Collectors.summarizingInt() method is passed as a parameter to the Stream.collect() method.
      • summarizingInt collector takes ToIntFunction instance as an input which in this case is specified using the method reference Click to Read Tutorial on Java 8's Method References to Employee’s age, i.e. “Employee::getAge”. This method reference acts as the ToIntFunction instance which extracts the age(of type int) from all Employee objects in the stream. An IntSummaryStatistics instance is then returned as output by the summarizing collector.
      • The output variable intSummaryStatistics is then printed and the age related statistics of all employees are correctly printed as shown in the output above.
    • Collectors.summarizingLong Collector
      • Collector returned by Collectors.summarizingLong() method is passed as a parameter to the Stream.collect() method.
      • summarizingLong collector takes ToLongFunction instance as an input which in this case is specified using the method reference to Employee’s leave, i.e. “Employee::getLeaves”. This method reference acts as the ToLongFunction instance which extracts the leaves(of type long) from all Employee objects in the stream. A LongSummaryStatistics instance is then returned as output by the summarizing collector.
      • The output variable longSummaryStatistics is then printed and the leaves related statistics of all employees are correctly printed as shown in the output above.
    • Collectors.summarizingDouble Collector
      • Collector returned by Collectors.summarizingDouble() method is passed as a parameter to the Stream.collect() method.
      • summarizingDouble collector takes ToDoubleFunction instance as an input which in this case is specified using the method reference to Employee’s salary, i.e. “Employee::getSalary”. This method reference acts as the ToDoubleFunction instance which extracts the salary(of type double) from all Employee objects in the stream. An DoubleSummaryStatistics instance is then returned as output by the summarizing collector.
      • The output variable doubleSummaryStatistics is then printed and the leaves related statistics of all employees are correctly printed as shown in the output above.