Coding problem · Medium · Language Idioms
Reporting with Streams and Collectors
Medium Language practicals Most askedSeen at Amazon, Goldman Sachs, JPMorgan, Atlassian
Given record Employee(String name, String dept, double salary), implement a Reports class with static methods:
Map<String, Long> countByDepartment(List<Employee> employees)Map<String, Double> averageSalaryByDepartment(List<Employee> employees)List<String> topEarners(List<Employee> employees, int n)— names of thenhighest salaries, highest firstMap<String, List<String>> namesByDepartment(List<Employee> employees)— names sorted alphabetically per department
Use streams and Collectors rather than manual loops.
Hints
Hint 1
Collectors.groupingBy(Employee::dept, Collectors.counting())
Hint 2
Downstream collectors: averagingDouble, mapping(..., toList()), collectingAndThen to sort.
Write and run your solution
Loading the editor… (JavaScript is required to run code in your browser.)
Solution and explanation
Show the solution
Time O(n log n) where sorting is involved · Space O(n)
groupingBy(classifier, downstream) is the workhorse: the downstream collector decides what each group becomes — a count, an average, or a mapped list. collectingAndThen post-processes each group (here, sorting names). Stream.toList() (Java 16+) returns an unmodifiable list. Records give you constructors, accessors, equals/hashCode and toString for free.
Reference solution
record Employee(String name, String dept, double salary) {}
class Reports {
static Map<String, Long> countByDepartment(List<Employee> employees) {
return employees.stream().collect(Collectors.groupingBy(Employee::dept, Collectors.counting()));
}
static Map<String, Double> averageSalaryByDepartment(List<Employee> employees) {
return employees.stream().collect(Collectors.groupingBy(Employee::dept, Collectors.averagingDouble(Employee::salary)));
}
static List<String> topEarners(List<Employee> employees, int n) {
return employees.stream()
.sorted(Comparator.comparingDouble(Employee::salary).reversed())
.limit(n)
.map(Employee::name)
.toList();
}
static Map<String, List<String>> namesByDepartment(List<Employee> employees) {
return employees.stream().collect(Collectors.groupingBy(
Employee::dept,
Collectors.collectingAndThen(
Collectors.mapping(Employee::name, Collectors.toList()),
names -> names.stream().sorted().toList())));
}
}
Common mistakes
- Using
Comparator.comparing(Employee::salary)on a primitive withoutcomparingDouble(boxing). - Assuming
groupingByreturns a sorted map — wrap withTreeMap::newif order matters.
Follow-up questions
- Partition by salary threshold with
partitioningBy. - Use a
TreeMapsupplier for sorted departments.