Definition
- groupingBy(dept, summingDouble(salary)) produces
Mapwith total salary per department. - entrySet().stream().max(comparingByValue()) finds the department with the highest total.
- BigDecimal precision: use
reducing(BigDecimal.ZERO, getSalary, BigDecimal::add)for exact totals. - Same two-step pattern as highest average and most employees, just with a different downstream.
The National Bank of India CFO asks: 'Which department costs us the most in salaries?' First sum all salaries per department, then find the department with the highest sum.
Understanding the Concepts
What does this question ask?
The two-step group-then-max pattern applied to total salary expenditure.
How do you find the highest total salary department?
package com.bank.hr;
import java.util.*;
import java.util.stream.Collectors;
public class HighestTotalSalary {
public static void main(String[] args) {
List<Employee> employees = Employee.getSampleEmployees();
Map<String, Double> totalByDept = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.summingDouble(
e -> e.getSalary().doubleValue())));
Optional<Map.Entry<String, Double>> highest = totalByDept.entrySet()
.stream()
.max(Map.Entry.comparingByValue());
highest.ifPresent(e ->
System.out.printf("Highest expenditure: %s (Rs.%.2f)%n",
e.getKey(), e.getValue()));
totalByDept.entrySet().stream()
.sorted(Map.Entry.<String, Double>comparingByValue().reversed())
.forEach(e -> System.out.printf(" %s: Rs.%.2f%n",
e.getKey(), e.getValue()));
}
}
Highest expenditure: TRADING (Rs.4500000.00)
TRADING: Rs.4500000.00
RISK: Rs.3600000.00
COMPLIANCE: Rs.2100000.00
OPERATIONS: Rs.1800000.00
How do you use exact BigDecimal arithmetic?
import java.math.BigDecimal;
Map<String, BigDecimal> exactTotals = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.reducing(
BigDecimal.ZERO,
Employee::getSalary,
BigDecimal::add)));
exactTotals.forEach((dept, total) ->
System.out.println(dept + ": Rs." + total));
How is summingDouble different from counting and averaging?
| Downstream | Result type | What it computes |
|---|---|---|
| counting() | Long | Number of elements |
| summingDouble(salary) | Double | Sum of salary values |
| averagingDouble(salary) | Double | Mean of salary values |
| summarizingDouble(salary) | DoubleSummaryStatistics | All five metrics |
What are common mistakes?
Mistake: using summingInt for BigDecimal salary.
// WRONG: summingInt expects ToIntFunction, not BigDecimal
Collectors.summingInt(Employee::getSalary); // compile error
// CORRECT: summingDouble with conversion
Collectors.summingDouble(e -> e.getSalary().doubleValue());
// BEST: reducing with BigDecimal for exact totals
Collectors.reducing(BigDecimal.ZERO, Employee::getSalary, BigDecimal::add);
What about computing budget percentage per department?
double grandTotal = totalByDept.values().stream()
.mapToDouble(Double::doubleValue).sum();
totalByDept.forEach((dept, total) ->
System.out.printf("%s: Rs.%,.0f (%.1f%%)%n",
dept, total, (total / grandTotal) * 100));
What about filtering departments above a threshold?
BigDecimal threshold = new BigDecimal("2000000");
List<String> highSpending = exactTotals.entrySet().stream()
.filter(e -> e.getValue().compareTo(threshold) > 0)
.map(Map.Entry::getKey)
.toList();
What are common interview follow-up questions?
- "How do you find the department with the lowest expenditure?" Replace max with min. - "How do you compute percentage of total budget per department?" First compute grand total, then divide each department total by it. - "How do you exclude departments under a threshold?" Filter the result map: `filter(e -> e.getValue() > threshold)`.
Visual Overview
Step 1: groupingBy(dept, summingDouble(salary)) ┌────────────────────────────────────┐ │ TRADING → Rs.4,500,000 │ │ RISK → Rs.3,600,000 │ │ COMPLIANCE → Rs.2,100,000 │ │ OPERATIONS → Rs.1,800,000 │ └────────────────────────────────────┘ Step 2: max(comparingByValue()) → TRADING (Rs.4,500,000) ← highest
Key Takeaway
Finding the department with the highest total salary uses the same two-step pattern: group with summingDouble, then max on the entrySet. For exact monetary totals, use Collectors.reducing(BigDecimal.ZERO, Employee::getSalary, BigDecimal::add) instead of summingDouble.
The two-step aggregate-then-max pattern is versatile: swap the downstream (counting, summing, averaging, summarizing) to answer different business questions with the same structural approach.
Remember one sentence: groupingBy with summingDouble gives total salary per department, then max on the entrySet identifies the highest-spending department.
---