Java Programs›Java 8 Streams›Find Average Salary by Department Using Streams

Find Average Salary by Department Using Streams in Java

intermediate·  Java 8 Streams  ·  Streams

Problem

Grouping with a downstream collector computes one summary value per group, like SQL's GROUP BY with AVG.

Given employees with a department and a salary, print the average salary of each department in alphabetical order.

Input
Engineering 85000, 95000; Sales 62000, 70000; HR 58000
Output
Engineering 90000.0, HR 58000.0, Sales 66000.0

Java Program

Java
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; public class AverageSalaryByDepartment { static class Employee { private final String dept; private final int salary; Employee(String dept, int salary) { this.dept = dept; this.salary = salary; } String getDept() { return dept; } int getSalary() { return salary; } } public static void main(String[] args) { List<Employee> staff = Arrays.asList( new Employee("Engineering", 85000), new Employee("Sales", 62000), new Employee("Engineering", 95000), new Employee("HR", 58000), new Employee("Sales", 70000)); Map<String, Double> averages = staff.stream() .collect(Collectors.groupingBy( Employee::getDept, TreeMap::new, // departments in alphabetical order Collectors.averagingInt(Employee::getSalary))); // one average per department averages.forEach((dept, avg) -> System.out.printf("%-12s %.1f%n", dept, avg)); } }

Output

Engineering 90000.0 HR 58000.0 Sales 66000.0

Core Logic

One collector does all the work: group by department, and inside each group average the salaries.

How It Works
  1. 1Employee::getDept is the grouping key.
  2. 2TreeMap::new keeps departments in alphabetical order.
  3. 3Collectors.averagingInt(Employee::getSalary) averages each group and returns a Double.
  4. 4printf("%-12s %.1f%n") prints the department padded to 12 characters and the average with one decimal.
Engineering's two salaries, 85000 and 95000, average to 90000.0.
💡

Key Point: averagingInt always returns a Double, even when every salary is a whole number.

Complexity
Time Complexity: O(n log d)Space Complexity: O(d)

Why: Each employee is added once to a TreeMap with d departments, which stores one running average per department.

Key Concepts

Collectors.groupingBy()Collectors.averagingInt()TreeMapprintf

Approach 2: Count, Total and Max per Department

Java
import java.util.Arrays; import java.util.IntSummaryStatistics; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; public class SalaryStatsByDepartment { static class Employee { private final String dept; private final int salary; Employee(String dept, int salary) { this.dept = dept; this.salary = salary; } String getDept() { return dept; } int getSalary() { return salary; } } public static void main(String[] args) { List<Employee> staff = Arrays.asList( new Employee("Engineering", 85000), new Employee("Sales", 62000), new Employee("Engineering", 95000), new Employee("HR", 58000), new Employee("Sales", 70000)); Map<String, IntSummaryStatistics> stats = staff.stream() .collect(Collectors.groupingBy(Employee::getDept, TreeMap::new, Collectors.summarizingInt(Employee::getSalary))); // count, sum, min, max, average at once stats.forEach((dept, s) -> System.out.println(dept + ": count=" + s.getCount() + ", total=" + s.getSum() + ", max=" + s.getMax())); } }

Output

Engineering: count=2, total=180000, max=95000 HR: count=1, total=58000, max=58000 Sales: count=2, total=132000, max=70000

Core Logic

summarizingInt collects count, sum, minimum, maximum and average for each group in a single pass.

How It Works
  1. 1The grouping is the same, but the downstream collector is summarizingInt.
  2. 2Each department maps to an IntSummaryStatistics object.
  3. 3The loop prints the count, total and maximum for each department.
Sales has two employees totalling 132000, with a maximum of 70000.
💡

Key Point: Use one summarizingInt instead of separate counting, summingInt and maxBy passes when you need several numbers.

Complexity
Time Complexity: O(n log d)Space Complexity: O(d)

Why: One pass updates a statistics object per department.

Key Concepts

Collectors.summarizingInt()IntSummaryStatistics

Interview Questions

How do you find the department with the highest average salary?

Stream the result map's entries and take max(Map.Entry.comparingByValue()), then read its key.

How would you round the averages to two decimals?

Format them when printing with %.2f, or wrap the value in BigDecimal and call setScale(2, RoundingMode.HALF_UP).

Learn the Concept

Related Programs