Back to Stream Practice: Employee Analysis
Q5Question 5 of 43

Find the department with the highest number of employees

Key Concepts
  • groupingBy(department, counting()) produces Map<String, Long> with headcount per department
  • entrySet().stream().max(Map.Entry.comparingByValue()) finds the entry with the highest count
  • The two-step pattern (group-then-max) is one of the most common stream interview questions
  • To handle ties, find the maxCount first, then filter all entries matching that count
  • Map.Entry.comparingByValue() and comparingByKey() are the standard Map entry comparators
  • collectingAndThen can combine both steps into a single collect call

Definition

Group by department with counting(), then stream the entrySet and find max by value to get the department with the most employees.
  • Step 1: groupingBy(Employee::getDepartment, counting()) produces Map with the headcount per department.
  • Step 2: entrySet().stream().max(Map.Entry.comparingByValue()) returns Optional> containing the department with the highest count.
  • Ties: If two departments have the same max count, max returns one arbitrarily. To find all tied departments, compute maxCount first, then filter.
  • One-liner: Use collectingAndThen to chain both steps inside a single collect call.
  • Smallest department: Replace max with min in step 2.

The National Bank of India capacity planner asks: "Which department has the most employees?" First, count how many people sit on each floor of the building. That gives a table: Floor 1 has 5, Floor 2 has 8, Floor 3 has 3. Then scan the table for the highest number. Floor 2 wins with 8. If Floor 1 and Floor 2 both have 8, they are tied.

Understanding the Concepts

What does this question ask?

The interviewer wants you to find which department has the most employees. This is a two-step stream problem: first aggregate (group and count), then find the extreme (max on the aggregated map). This pattern appears frequently in interviews because it tests both groupingBy and entrySet streaming.

How do you count employees per department?

JAVA
package com.bank.hr;

import java.util.*;
import java.util.stream.Collectors;

public class HeadcountByDept {
    public static void main(String[] args) {
        List<Employee> employees = Employee.getSampleEmployees();

        Map<String, Long> countByDept = employees.stream()
            .collect(Collectors.groupingBy(
                Employee::getDepartment,
                Collectors.counting()));

        countByDept.forEach((dept, count) ->
            System.out.println(dept + ": " + count));
    }
}
TEXT
TRADING: 3
RISK: 3
OPERATIONS: 2
COMPLIANCE: 2

How do you find the department with the highest count?

Stream the Map's entrySet and use max with Map.Entry.comparingByValue().

JAVA
package com.bank.hr;

import java.util.*;
import java.util.stream.Collectors;

public class LargestDepartment {
    public static void main(String[] args) {
        List<Employee> employees = Employee.getSampleEmployees();

        Map<String, Long> countByDept = employees.stream()
            .collect(Collectors.groupingBy(
                Employee::getDepartment,
                Collectors.counting()));

        Optional<Map.Entry<String, Long>> largest = countByDept.entrySet()
            .stream()
            .max(Map.Entry.comparingByValue());

        largest.ifPresent(e ->
            System.out.println("Largest: " + e.getKey()
                + " (" + e.getValue() + " employees)"));
    }
}
TEXT
Largest: TRADING (3 employees)

The result is Optional>. Use map(Map.Entry::getKey) to extract just the department name.

How do you write it as a one-liner?

JAVA
String largestDept = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDepartment, Collectors.counting()))
    .entrySet().stream()
    .max(Map.Entry.comparingByValue())
    .map(e -> e.getKey() + " (" + e.getValue() + " employees)")
    .orElse("No departments");

System.out.println(largestDept);
TEXT
TRADING (3 employees)

The one-liner chains collect, entrySet, stream, max, and map. In interviews, the two-step version is easier to explain.

How do you handle ties?

If two departments have the same count, max returns one arbitrarily. To find all tied departments, compute the max count first, then filter.

JAVA
package com.bank.hr;

import java.util.*;
import java.util.stream.Collectors;

public class TiedDepartments {
    public static void main(String[] args) {
        List<Employee> employees = Employee.getSampleEmployees();

        Map<String, Long> countByDept = employees.stream()
            .collect(Collectors.groupingBy(
                Employee::getDepartment, Collectors.counting()));

        long maxCount = countByDept.values().stream()
            .mapToLong(Long::longValue)
            .max()
            .orElse(0);

        List<String> tiedDepts = countByDept.entrySet().stream()
            .filter(e -> e.getValue() == maxCount)
            .map(Map.Entry::getKey)
            .toList();

        System.out.println("Max count: " + maxCount);
        System.out.println("Tied departments: " + tiedDepts);
    }
}
TEXT
Max count: 3
Tied departments: [TRADING, RISK]

How do you rank all departments by size?

Sort the entrySet by value descending and collect to a LinkedHashMap to preserve order.

JAVA
package com.bank.hr;

import java.util.*;
import java.util.stream.Collectors;

public class DepartmentRanking {
    public static void main(String[] args) {
        List<Employee> employees = Employee.getSampleEmployees();

        LinkedHashMap<String, Long> ranked = employees.stream()
            .collect(Collectors.groupingBy(
                Employee::getDepartment, Collectors.counting()))
            .entrySet().stream()
            .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (a, b) -> a,
                LinkedHashMap::new));

        int rank = 1;
        for (var entry : ranked.entrySet()) {
            System.out.println(rank++ + ". " + entry.getKey()
                + ": " + entry.getValue());
        }
    }
}
TEXT
1. TRADING: 3
2. RISK: 3
3. OPERATIONS: 2
4. COMPLIANCE: 2

What are common mistakes?

Mistake 1: trying to find max on the original employee stream instead of the grouped map.

JAVA
// WRONG: this finds the employee with the "largest" department name alphabetically
Optional<Employee> wrong = employees.stream()
    .max(Comparator.comparing(Employee::getDepartment));

// CORRECT: group first, then find max count
Optional<Map.Entry<String, Long>> correct = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDepartment, Collectors.counting()))
    .entrySet().stream()
    .max(Map.Entry.comparingByValue());

Mistake 2: forgetting that you need a second stream on the entrySet.

JAVA
// WRONG: Map has no max method
// countByDept.max(...)  // does not compile

// CORRECT: stream the entrySet
countByDept.entrySet().stream().max(Map.Entry.comparingByValue());

Mistake 3: using Collections.max instead of stream for the Map values.

JAVA
// Works but less idiomatic:
Long maxVal = Collections.max(countByDept.values());
// Then you need a separate step to find which key has that value

// More idiomatic: stream the entrySet
countByDept.entrySet().stream()
    .max(Map.Entry.comparingByValue());

How do you combine both steps using collectingAndThen?

JAVA
Optional<Map.Entry<String, Long>> result = employees.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.groupingBy(Employee::getDepartment, Collectors.counting()),
        map -> map.entrySet().stream()
            .max(Map.Entry.comparingByValue())));

This wraps the two-step logic inside a single collect call. The finisher function takes the grouped map and finds the max entry.

What are common interview follow-up questions?

  • "How do you find the smallest department?" Replace max with min.
  • "How do you find the department with the highest total salary?" Change the downstream to summingDouble(salary) instead of counting().
  • "How do you find the department with the highest average salary?" Use averagingDouble(salary) as the downstream, then max on the values.
  • "How do you exclude departments with fewer than 3 employees?" Filter the entrySet: filter(e -> e.getValue() >= 3).

Visual Overview

DIAGRAM
  Step 1: Group and Count

  Stream<Employee>
       │
       │  .collect(groupingBy(dept, counting()))
       ▼
  ┌──────────────────────────┐
  │  Map<String, Long>       │
  │  TRADING ───→ 3          │
  │  RISK ──────→ 3          │
  │  OPERATIONS → 2          │
  │  COMPLIANCE → 2          │
  └──────────────────────────┘

  Step 2: Find Max Entry

  entrySet().stream()
       │
       │  .max(comparingByValue())
       ▼
  Optional<Entry<"TRADING", 3>>

Key Takeaway

Finding the department with the most employees is a two-step stream operation. Step one groups by department with counting as the downstream: groupingBy(Employee::getDepartment, counting()) produces Map. Step two streams the entrySet and finds the max by value: entrySet().stream().max(Map.Entry.comparingByValue()).

The key insight is that groupingBy produces a Map, and you need a second stream on the Map's entrySet to find the max or min entry. The comparators Map.Entry.comparingByValue() and comparingByKey() are the standard tools for comparing map entries.

To handle ties where multiple departments share the same max count, find the maxCount first, then filter all entries matching that count. For a complete ranking, sort the entrySet by value descending and collect to a LinkedHashMap.

Remember one sentence: group by department with counting to get a Map of headcounts, then stream the entrySet and find max by value to identify the largest department.

---

Share
Use ← → arrow keys to navigate