Back to Stream Practice: Employee Analysis
Q29Question 29 of 43

Find the most common city among employees

Key Concepts
  • groupingBy(getCity, counting()) produces Map<String, Long> of employee count per city
  • entrySet().stream().max(comparingByValue()) finds the city with the most employees
  • This is the same two-step group-then-max pattern used for department questions
  • Handle ties by finding maxCount first, then filtering all cities matching it
  • The pattern works for any 'most common X' question: replace getCity with any field getter
  • Use Collectors.collectingAndThen to combine both steps if needed

Definition

Group by city with counting(), then find the max entry by value to identify the most common city.
  • groupingBy(getCity, counting()) produces Map of headcount per city.
  • max(comparingByValue()) on the entrySet finds the city with the highest count.
  • Same pattern as department-with-most-employees, just grouped by city instead.
  • Ties: find maxCount, then filter all entries matching it.

The bank wants to know which city has the most employees. Count employees per city, then pick the city with the highest count.

Understanding the Concepts

How do you find the most common city?

JAVA
package com.bank.hr;

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

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

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

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

        mostCommon.ifPresent(e ->
            System.out.println("Most common: " + e.getKey()
                + " (" + e.getValue() + " employees)"));
    }
}
TEXT
Most common: Mumbai (4 employees)

How do you handle ties?

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

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

What are common mistakes?

Mistake: using distinct().count() to find the most common value.

JAVA
// WRONG: distinct gives unique cities, not the most common
long uniqueCities = employees.stream()
    .map(Employee::getCity)
    .distinct()
    .count();

// CORRECT: group and count, then max

What about finding the least common city?

Replace max with min:

JAVA
Optional<Map.Entry<String, Long>> leastCommon = countByCity
    .entrySet().stream()
    .min(Map.Entry.comparingByValue());

How do you rank all cities by employee count?

JAVA
countByCity.entrySet().stream()
    .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
    .forEach(e -> System.out.println(
        e.getKey() + ": " + e.getValue()));

What about finding the most common value for any field?

The group-count-max pattern works for any field:

JAVA
// Most common department
Optional<String> topDept = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDepartment, Collectors.counting()))
    .entrySet().stream()
    .max(Map.Entry.comparingByValue())
    .map(Map.Entry::getKey);

What about finding the top N most common cities?

JAVA
List<String> topThree = countByCity.entrySet().stream()
    .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
    .limit(3)
    .map(Map.Entry::getKey)
    .toList();

System.out.println("Top 3 cities: " + topThree);

What are the edge cases?

If no employees exist, the map is empty and max returns Optional.empty(). If all employees share the same city, that city is the sole entry.

What should a senior engineer know?

At National Bank of India, Rajesh uses this pattern in the HR analytics dashboard to decide where to open new branch offices. The query runs on 50,000+ employee records. For large datasets, the groupingBy collector builds a HashMap internally, so the time complexity is O(n) for grouping and O(k) for finding the max, where k is the number of unique cities.

JAVA
// Production pattern: find the city with the most employees
// and the average salary in that city for branch planning
String topCity = employees.stream()
    .collect(Collectors.groupingBy(Employee::getCity, Collectors.counting()))
    .entrySet().stream()
    .max(Map.Entry.comparingByValue())
    .map(Map.Entry::getKey)
    .orElse("N/A");

BigDecimal avgSalary = employees.stream()
    .filter(e -> e.getCity().equals(topCity))
    .map(Employee::getSalary)
    .reduce(BigDecimal.ZERO, BigDecimal::add)
    .divide(BigDecimal.valueOf(
        employees.stream().filter(e -> e.getCity().equals(topCity)).count()),
        2, java.math.RoundingMode.HALF_UP);

For parallel streams, use groupingByConcurrent which returns a ConcurrentHashMap and avoids the merge step.

What are common interview follow-up questions?

  • "How do you find the least common city?" Replace max with min.
  • "How do you find the most common department in each city?" Nest groupingBy(city, groupingBy(dept, counting())), then find max within each city.

Visual Overview

DIAGRAM
  groupingBy(city, counting())
  ┌──────────────────────────┐
  │  Mumbai   → 4            │ ← max
  │  Delhi    → 3            │
  │  Chennai  → 2            │
  │  Pune     → 1            │
  └──────────────────────────┘
  max(comparingByValue()) → Mumbai (4)

Key Takeaway

Finding the most common city uses the familiar group-then-max pattern: groupingBy(getCity, counting()) produces a frequency map, then max(comparingByValue()) on the entrySet finds the city with the highest count. The same pattern works for any 'most common X' question.

Remember one sentence: group by the field, count, then max by value to find the most common value of any field.

---

Share
Use ← → arrow keys to navigate