Definition
- groupingBy(dept, summarizingInt(age)) gives
Mapwith min, max, count, sum, avg per department. - Range =
stats.getMax() - stats.getMin()per department. - max(comparing(range)) on the entrySet finds the most diverse department.
- Single-employee departments have range 0.
The bank's diversity team asks: 'Which department has the widest age gap between youngest and oldest?' Compute the min and max age per department, subtract, and pick the largest difference.
Understanding the Concepts
How do you find the department with the widest age range?
package com.bank.hr;
import java.util.*;
import java.util.stream.Collectors;
public class MostDiverseAgeRange {
public static void main(String[] args) {
List<Employee> employees = Employee.getSampleEmployees();
Map<String, IntSummaryStatistics> statsByDept = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.summarizingInt(Employee::getAge)));
Optional<Map.Entry<String, IntSummaryStatistics>> widest =
statsByDept.entrySet().stream()
.max(Comparator.comparingInt(
e -> e.getValue().getMax() - e.getValue().getMin()));
widest.ifPresent(e -> {
IntSummaryStatistics s = e.getValue();
System.out.printf("%s: range = %d (min=%d, max=%d)%n",
e.getKey(),
s.getMax() - s.getMin(),
s.getMin(), s.getMax());
});
}
}
RISK: range = 27 (min=28, max=55)
What are common mistakes?
Mistake: computing max and min with separate streams instead of summarizingInt.
// Inefficient: two passes per department
// Use summarizingInt for both min and max in one pass
What about the teeing approach for min and max?
Java 12+ teeing can collect min and max in one pass without summarizingInt:
Map<String, int[]> ranges = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.teeing(
Collectors.minBy(Comparator.comparingInt(Employee::getAge)),
Collectors.maxBy(Comparator.comparingInt(Employee::getAge)),
(min, max) -> new int[]{
min.map(Employee::getAge).orElse(0),
max.map(Employee::getAge).orElse(0)})));
What about excluding departments with fewer than 3 employees?
statsByDept.entrySet().stream()
.filter(e -> e.getValue().getCount() >= 3)
.max(Comparator.comparingInt(
e -> e.getValue().getMax() - e.getValue().getMin()))
.ifPresent(e -> System.out.println(e.getKey()));
What about finding the department with the smallest range?
Replace max with min in the comparator.
What about the summarizingDouble alternative?
Instead of summarizingInt for ages, use summarizingDouble for salary ranges.
import java.util.DoubleSummaryStatistics;
Map<String, DoubleSummaryStatistics> salaryStats = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.summarizingDouble(e -> e.getSalary().doubleValue())));
What about finding the average age range across departments?
double avgRange = statsByDept.values().stream()
.mapToInt(s -> s.getMax() - s.getMin())
.average().orElse(0);
System.out.println("Average age range: " + avgRange);
What are the edge cases?
A department with one employee has range 0. A department with two employees has range equal to the absolute difference between their ages.
What are common interview follow-up questions?
- "How do you find the department with the smallest range?" Replace max with min.
- "How do you exclude departments with fewer than 3 employees?" Filter stats by count >= 3.
Visual Overview
groupingBy(dept, summarizingInt(age)) ┌──────────────────────────────────────────────┐ │ TRADING → min=28, max=45 range=17 │ │ RISK → min=28, max=55 range=27 ← max│ │ OPERATIONS → min=32, max=58 range=26 │ │ COMPLIANCE → min=29, max=52 range=23 │ └──────────────────────────────────────────────┘
Key Takeaway
Finding the most diverse age range per department uses summarizingInt(age) as the downstream to get min and max in one pass, then computes max - min for each department and finds the largest range.
Remember one sentence: summarizingInt gives min, max, and more in one pass, and max - min gives the age range per department.
---