Back to Stream Practice: Employee Analysis
Q31Question 31 of 43

Find the youngest male and female employee

Key Concepts
  • groupingBy(gender, minBy(comparingInt(age))) finds the youngest per gender in one pass
  • The result is Map<String, Optional<Employee>> because minBy returns Optional
  • collectingAndThen unwraps the Optional for cleaner access
  • Alternatively: filter by gender first, then min separately for each gender (two passes)
  • minBy for youngest (smallest age), maxBy for oldest (largest age)
  • For youngest per department per gender, nest three levels of groupingBy

Definition

Use groupingBy(gender, minBy(comparingInt(age))) to find the youngest male and youngest female employee in a single pass.
  • groupingBy(gender, minBy(comparingInt(age))) produces Map> with the youngest per gender.
  • collectingAndThen unwraps Optional: collectingAndThen(minBy(...), Optional::orElseThrow).
  • Alternative: filter by gender, then min separately. Simpler but requires two passes.
  • minBy finds the minimum (youngest age); maxBy finds the maximum (oldest age).

The bank's youth mentorship program needs the youngest male and youngest female employee. Sort each gender's pile by age and pick the top card from each.

Understanding the Concepts

How do you find the youngest per gender?

JAVA
package com.bank.hr;

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

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

        Map<String, Optional<Employee>> youngest = employees.stream()
            .collect(Collectors.groupingBy(
                Employee::getGender,
                Collectors.minBy(
                    Comparator.comparingInt(Employee::getAge))));

        youngest.forEach((gender, opt) ->
            opt.ifPresent(e -> System.out.printf(
                "Youngest %s: %s, age %d%n",
                gender, e.getName(), e.getAge())));
    }
}
TEXT
Youngest M: Amit, age 35
Youngest F: Priya, age 28

Alternative: filter then min for each gender

JAVA
Optional<Employee> youngestMale = employees.stream()
    .filter(e -> "M".equals(e.getGender()))
    .min(Comparator.comparingInt(Employee::getAge));

Optional<Employee> youngestFemale = employees.stream()
    .filter(e -> "F".equals(e.getGender()))
    .min(Comparator.comparingInt(Employee::getAge));

How do you unwrap Optional from the result?

JAVA
Map<String, Employee> unwrapped = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getGender,
        Collectors.collectingAndThen(
            Collectors.minBy(Comparator.comparingInt(Employee::getAge)),
            Optional::orElseThrow)));

What are common mistakes?

Mistake: using maxBy instead of minBy for youngest.

JAVA
// WRONG: maxBy finds the OLDEST
Collectors.maxBy(Comparator.comparingInt(Employee::getAge));

// CORRECT: minBy finds the YOUNGEST
Collectors.minBy(Comparator.comparingInt(Employee::getAge));

What about finding both youngest and oldest using teeing?

JAVA
import java.util.stream.Collectors;

record AgePair(Employee youngest, Employee oldest) {}

Map<String, AgePair> pairs = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getGender,
        Collectors.teeing(
            Collectors.minBy(Comparator.comparingInt(Employee::getAge)),
            Collectors.maxBy(Comparator.comparingInt(Employee::getAge)),
            (min, max) -> new AgePair(
                min.orElseThrow(), max.orElseThrow()))));

teeing (Java 12+) applies two downstream collectors and merges their results.

What about the edge case of a single employee?

If a gender has only one employee, that employee is both the youngest and the oldest. minBy and maxBy both return the same person.

What about using records for clean output?

JAVA
record EmployeeSummary(String name, int age, String department) {
    static EmployeeSummary from(Employee e) {
        return new EmployeeSummary(e.getName(), e.getAge(), e.getDepartment());
    }
}

What are common interview follow-up questions?

  • "How do you find both youngest and oldest per gender?" Use teeing with minBy and maxBy.
  • "How do you handle ties?" minBy returns the first one in encounter order.
  • "How do you find youngest per department per gender?" Nest three groupingBy levels.

Visual Overview

DIAGRAM
  groupingBy(gender, minBy(comparingInt(age)))

  ┌──────────────────────────────────────┐
  │  M → [Rajesh 45, Amit 35, Suresh 58, │
  │       Deepak 55, Vikram 52]          │
  │     minBy(age) → Amit (35)           │
  │                                      │
  │  F → [Priya 28, Kavita 40, Neha 32,  │
  │       Ananya 29, Meera 38]           │
  │     minBy(age) → Priya (28)          │
  └──────────────────────────────────────┘

Key Takeaway

Finding the youngest male and female uses groupingBy(gender, minBy(comparingInt(age))) which produces a Map with the youngest employee per gender in one pass. The minBy downstream returns Optional, which can be unwrapped with collectingAndThen.

The alternative is two separate filter-then-min passes, one for each gender. The groupingBy approach is more concise and handles any number of gender values automatically.

Remember one sentence: groupingBy with minBy finds the extreme value per group in one pass, and minBy is for youngest (smallest age) while maxBy is for oldest.

---

Share
Use ← → arrow keys to navigate