Back to Stream Practice: Employee Analysis
Q32Question 32 of 43

For each department, find the ratio of male to female employees

Key Concepts
  • Nested groupingBy(dept, groupingBy(gender, counting())) gives per-department gender counts
  • Compute ratio as maleCount / femaleCount per department from the nested map
  • Handle division by zero when a department has no female employees
  • Use partitioningBy as the inner downstream for a guaranteed true/false split
  • Display as percentage or M:F ratio format
  • This combines multi-level aggregation with post-processing arithmetic

Definition

Nest groupingBy(dept, groupingBy(gender, counting())) to get per-department gender counts, then compute the male-to-female ratio from the nested map.
  • Nested groupingBy produces Map> of dept to gender to count.
  • Ratio = maleCount / femaleCount per department.
  • Division by zero: handle departments with zero females using getOrDefault("F", 0L) with a guard.
  • Alternative: use partitioningBy(isMale, counting()) as the inner downstream.

The diversity team at the bank asks: 'For each department, what is the ratio of male to female employees?' Count males and females per department, then divide.

Understanding the Concepts

How do you compute the male-to-female ratio per department?

JAVA
package com.bank.hr;

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

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

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

        deptGender.forEach((dept, genderMap) -> {
            long male = genderMap.getOrDefault("M", 0L);
            long female = genderMap.getOrDefault("F", 0L);
            String ratio = female > 0
                ? String.format("%.2f:1", (double) male / female)
                : male + ":0 (no females)";
            System.out.printf("%s: M=%d, F=%d, ratio=%s%n",
                dept, male, female, ratio);
        });
    }
}
TEXT
TRADING: M=2, F=1, ratio=2.00:1
RISK: M=1, F=2, ratio=0.50:1
OPERATIONS: M=1, F=1, ratio=1.00:1
COMPLIANCE: M=1, F=1, ratio=1.00:1

What are common mistakes?

Mistake: not handling division by zero.

JAVA
// WRONG: ArithmeticException if no females
double ratio = (double) male / female;  // female = 0 → Infinity

// CORRECT: guard against zero
String safe = female > 0
    ? String.format("%.2f:1", (double) male / female)
    : "all male";

What about using partitioningBy for the inner split?

JAVA
Map<String, Map<Boolean, Long>> deptParity = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDepartment,
        Collectors.partitioningBy(
            e -> "M".equals(e.getGender()),
            Collectors.counting())));

// partitioningBy guarantees both true and false keys

partitioningBy as the inner downstream guarantees both male (true) and female (false) keys exist, eliminating the need for getOrDefault.

What about displaying as a percentage?

JAVA
deptGender.forEach((dept, genderMap) -> {
    long male = genderMap.getOrDefault("M", 0L);
    long female = genderMap.getOrDefault("F", 0L);
    long total = male + female;
    System.out.printf("%s: Male %.0f%%, Female %.0f%%%n",
        dept,
        (double) male / total * 100,
        (double) female / total * 100);
});

What about flagging departments with gender imbalance?

JAVA
deptGender.forEach((dept, genderMap) -> {
    long male = genderMap.getOrDefault("M", 0L);
    long female = genderMap.getOrDefault("F", 0L);
    long total = male + female;
    double malePercent = (double) male / total * 100;
    if (malePercent > 70 || malePercent < 30) {
        System.out.println("IMBALANCE: " + dept
            + " (" + malePercent + "% male)");
    }
});

What are the edge cases?

A department with zero employees would not appear in the result. A department with only male or only female employees would have a 0 in the other bucket (via getOrDefault), requiring the division-by-zero guard.

What are common interview follow-up questions?

  • "How do you flag departments with gender imbalance above 70%?" Compute percentage, then filter.
  • "How do you return the ratio as a record?" Create a record GenderRatio(String dept, long male, long female, double ratio) and map to it.

Visual Overview

DIAGRAM
  groupingBy(dept, groupingBy(gender, counting()))

  TRADING ──→ { M: 2, F: 1 } → ratio 2.00:1
  RISK ─────→ { M: 1, F: 2 } → ratio 0.50:1
  OPS ──────→ { M: 1, F: 1 } → ratio 1.00:1
  COMP ─────→ { M: 1, F: 1 } → ratio 1.00:1

Key Takeaway

Computing the gender ratio per department uses nested groupingBy(dept, groupingBy(gender, counting())) to get male and female counts per department, then divides male by female with a zero guard.

Remember one sentence: nest groupingBy twice for per-department per-gender counts, then compute the ratio with a division-by-zero guard.

---

Share
Use ← → arrow keys to navigate