Java 8 Summarizing Methods with Examples
-
Last Updated: May 4, 2024
-
By: javahandson
-
Series
Learn Java in a easy way
Java 8 Summarizing Methods help calculate count, sum, min, max, and average in a single stream operation. Learn summarizingInt(), summarizingLong(), summarizingDouble(), and IntSummaryStatistics with clear practical examples.
In Java 8, we get a set of summarizing methods in the Stream API through the Collectors class. These methods help us generate summary statistics for numeric data cleanly and efficiently.
In simple terms, Java 8 Summarizing Methods allow us to calculate count, sum, minimum, maximum, and average in a single stream operation. Instead of running multiple stream pipelines, we can collect all statistics at once. As a result, our code becomes shorter, clearer, and easier to maintain.
For example, when we process a list of numbers, we often need more than just the sum. We may also want the average, the highest value, and the lowest value. If we compute them separately, we must traverse the stream multiple times. However, summarizing methods solve this problem by performing all calculations in one pass.
Because of this approach, we reduce boilerplate code and improve efficiency. Therefore, when we work on reports, analytics, salary calculations, or performance metrics, these methods become extremely useful.
Overall, Java 8 Summarizing Methods give us a powerful and elegant way to extract statistical information from collections.
Java 8 provides three variants of summarizing methods. Each variant works with a specific numeric type, although the overall behavior remains the same.
We use:
summarizingInt() for int valuessummarizingLong() for long valuessummarizingDouble() for double valuesAll three methods follow the same pattern. However, we choose the appropriate one based on the numeric type we extract from the stream.
In the following sections, we will explore each method in detail with practical examples.
We use summarizingInt() When we want to compute statistics based on an int value extracted from stream elements.
Instead of performing multiple operations like sum, average, and min separately, we can calculate everything in one pass. As a result, our code becomes cleaner and more efficient.
public static <T> Collector<T, ?, IntSummaryStatistics>
summarizingInt(ToIntFunction<? super T> mapper> mapper)
Let us break this down in a practical way.
We call this method using the Collectors class, which is why it is declared as public static. Therefore, we simply use it like this:
Collectors.summarizingInt(...)
Next comes <T>. This represents the type of elements in the stream. For example, if we stream Student objects, then T becomes Student. Because of generics, this method works with any object type, which makes it flexible and reusable.
The return type is:
Collector<T, ?, IntSummaryStatistics>
This means the method returns a Collector that processes elements of type T and finally produces an IntSummaryStatistics object. That object contains all the calculated values, such as count, sum, minimum, maximum, and average. In other words, instead of returning a single number, the method returns a complete statistical summary.
Now, let us focus on the parameter:
ToIntFunction<? super T> mapper
This part tells Java how to extract a int value from each element in the stream. ToIntFunction is a functional interface that takes an object and returns an int.
For example:
Student::getMarks
Here, we take each Student object and extract the marks value. The stream then uses these extracted int values to compute all statistics in one pass.
Putting everything together, when we write:
Collectors.summarizingInt(Student::getMarks)
We instruct Java to:
StudentIntSummaryStatistics objectAlthough the signature looks advanced, it simply enables us to perform multiple statistical operations in a single, efficient stream pipeline. As a result, our code remains clean, expressive, and performance-friendly.
Suppose we want to calculate statistics on student marks.
package com.javahands.collectors.summarizing;
public class Student {
int rollNumber;
String name;
int marks;
public Student(int rollNumber, String name, int marks) {
this.rollNumber = rollNumber;
this.name = name;
this.marks = marks;
}
public int getMarks() {
return marks;
}
}
Using summarizingInt()
package com.javahands.collectors.summarizing;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.stream.Collectors;
public class SummarizingInt {
public static void main(String[] args) {
List<Student> studentList = Arrays.asList(
new Student(101, "Suraj", 450),
new Student(102, "Iqbal", 470),
new Student(103, "Amar", 430),
new Student(104, "Amit", 400),
new Student(105, "Suchit", 380),
new Student(106, "Kartik", 490));
IntSummaryStatistics marksStats = studentList.stream()
.collect(Collectors.summarizingInt(Student::getMarks));
System.out.println("Average marks: " + marksStats.getAverage());
System.out.println("Total marks: " + marksStats.getSum());
System.out.println("Maximum marks: " + marksStats.getMax());
System.out.println("Minimum marks: " + marksStats.getMin());
System.out.println("Number of marks: " + marksStats.getCount());
}
}
Output:
Average marks: 436.6666666666667
Total marks: 2620
Maximum marks: 490
Minimum marks: 380
Number of marks: 6
Here, we compute all statistics in a single stream traversal. Therefore, the solution remains both efficient and readable.
We use summarizingLong() When the extracted value is of type long. Although it behaves exactly like summarizingInt(), it works with larger numeric values.
Because of this, we prefer it when numbers might exceed the int range.
public static <T> Collector<T, ?, LongSummaryStatistics>
summarizingLong(ToLongFunction<? super T>mapper)
The summarizingLong() method follows the same pattern as summarizingInt(). However, it works with long values instead of int.
The key differences are straightforward.
Instead of ToIntFunction this method uses ToLongFunction. Therefore, we provide a mapping function that extracts a long value from each stream element.
Additionally, the method returns an LongSummaryStatistics object. This object stores count, sum, minimum, maximum, and average for long values.
Everything else remains the same. So, once we understand summarizingInt(), we can easily apply the same logic here. The only change lies in the numeric type we extract from the stream.
For example:
Collectors.summarizingLong(Product::getProductId)
Here, we extract the productId as a long and compute all statistics in a single stream operation.
Suppose we want to analyze product IDs stored as long values.
package com.javahands.collectors.summarizing;
public class Product {
long productId;
String productName;
double price;
public Product(long productId, String productName, double price) {
super();
this.productId = productId;
this.productName = productName;
this.price = price;
}
public long getProductId() {
return productId;
}
public void setProductId(long productId) {
this.productId = productId;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
Using summarizingLong()
package com.javahands.collectors.summarizing;
import java.util.Arrays;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.stream.Collectors;
public class SummarizingLong {
public static void main(String[] args) {
List<Product> products = Arrays.asList(
new Product(101l, "Wheat", 155.50),
new Product(102l, "Rice", 255.00),
new Product(103l, "Cooking Oil", 525.70),
new Product(104l, "Cookies", 200.00),
new Product(105l, "Beans", 150.50));
LongSummaryStatistics longSummaryStatistics = products.stream()
.collect(Collectors.summarizingLong(Product::getProductId));
System.out.println(longSummaryStatistics);
}
}
Output: LongSummaryStatistics{count=5, sum=515, min=101, average=103.000000, max=105}
Again, we compute everything in one operation. As a result, the code remains concise and efficient.
We use summarizingDouble() When the extracted value is of type double. This method becomes useful when we deal with decimal or precision values.
For example, we often use it for price, salary, or percentage calculations.
public static <T> Collector<T, ?, DoubleSummaryStatistics>
summarizingDouble(ToDoubleFunction<? super T> mapper)
The summarizingDouble() method follows the same structure as summarizingInt() and summarizingLong(). However, it works specifically with double values, which makes it suitable for precision-based data such as prices, percentages, or measurements.
Let us focus only on what changes here.
First, instead of ToIntFunction or ToLongFunction, this method uses ToDoubleFunction. That means we must provide a mapping function that extracts a double value from each stream element.
Second, the method returns a DoubleSummaryStatistics object. This object stores count, sum, minimum, maximum, and average for double values.
Everything else remains the same. Therefore, if we understand how summarizingInt() works, we already understand this method as well. The only difference lies in the numeric type we extract from the stream.
For example, when we write:
Collectors.summarizingDouble(Product::getPrice)
We instruct Java to extract the price data from each product and compute all statistics in a single pass.
Because of this design, we can efficiently process precision-based data without writing multiple stream operations.
package com.javahands.collectors.summarizing;
import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.stream.Collectors;
public class SummarizingDouble {
public static void main(String[] args) {
List<Product> products = Arrays.asList(
new Product(101l, "Wheat", 155.50),
new Product(102l, "Rice", 255.00),
new Product(103l, "Cooking Oil", 525.70),
new Product(104l, "Cookies", 200.00),
new Product(105l, "Beans", 150.50));
DoubleSummaryStatistics doubleSummaryStatistics = products.stream()
.collect(Collectors.summarizingDouble(Product::getPrice));
System.out.println(doubleSummaryStatistics);
}
}
Output: DoubleSummaryStatistics{count=5, sum=1286.700000, min=150.500000, average=257.340000, max=525.700000}
Because we collect all statistics together, we avoid multiple stream operations. Therefore, our implementation remains both elegant and practical.
All three summarizing methods follow the same pattern. The only difference lies in the numeric type we extract:
summarizingInt() → for int valuessummarizingLong() → for long valuessummarizingDouble() → for double valuesWhenever we need multiple statistics from a stream, these methods provide the cleanest solution.
Java 8 Summarizing Methods provide a clean and efficient way to compute multiple statistics in a single stream operation. Instead of writing separate logic for sum, average, minimum, maximum, and count, we can collect all values at once using summarizingInt(), summarizingLong(), or summarizingDouble().
Because these methods return summary statistics objects, we gain both clarity and performance. As a result, our code becomes more expressive and easier to maintain. Whether we work with student marks, product IDs, or price calculations, summarizing methods help us write concise and production-ready stream pipelines.
In real-world applications such as reporting, analytics, or financial computations, Java 8 Summarizing Methods allow us to extract meaningful insights with minimal code. Therefore, understanding these collectors strengthens our overall command of the Java 8 Stream API.
For the official documentation and complete details about summarizing collectors, see:
Collectors API – Java 8 Documentation (Oracle)
The official Java documentation explains how summarizingInt(), summarizingLong(), and summarizingDouble() work internally, along with other powerful collectors available in the Stream API.
We can also explore: IntSummaryStatistics, LongSummaryStatistics, and DoubleSummaryStatistics – Java API Docs
These classes define how summary statistics such as count, sum, min, max, and average are computed and stored.
In the next chapter, we move from calculating numeric summaries to organizing data into structured groups.
Grouping in Java 8 introduces the Collectors.groupingBy() method, which allows us to categorize stream elements based on specific properties. With grouping, we can transform flat collections into meaningful data structures such as maps of lists or aggregated results.
This shift takes us from summarizing values to structuring data, which is a powerful next step in mastering the Java 8 Stream API.