Back to Stream Practice: Employee Analysis
Q18Question 18 of 43

Find the employee who joined most recently

Key Concepts
  • max(comparing(Employee::getJoinDate)) returns Optional<Employee> for the most recent joiner
  • LocalDate implements Comparable, so naturalOrder() comparator works directly
  • For per-department most recent, use groupingBy(dept, maxBy(comparing(joinDate)))
  • max on an empty stream returns Optional.empty(), always handle the empty case
  • To find the earliest joiner, use min instead of max
  • For ties (same date), max returns the first one in encounter order

Definition

Use stream().max(Comparator.comparing(Employee::getJoinDate)) to find the employee with the latest joining date.
  • max(comparing(joinDate)) returns Optional containing the employee with the most recent (latest) joining date.
  • LocalDate implements Comparable, so Comparator.comparing(Employee::getJoinDate) uses natural ordering (chronological).
  • Per-department: groupingBy(dept, maxBy(comparing(joinDate))) finds the most recent joiner in each department.
  • Earliest joiner: use min instead of max to find the oldest joining date.

Rajesh at the National Bank of India asks HR: 'Who is our newest hire?' HR scans the joining dates of all employees and picks the one with the latest date. That scan is what max(comparing(joinDate)) does.

Understanding the Concepts

What does this question ask?

The interviewer wants you to find the maximum value of a date field in a stream. This tests Stream.max, Comparator.comparing, and Optional handling.

How do you find the most recent joiner?

JAVA
package com.bank.hr;

import java.time.LocalDate;
import java.util.*;

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

        Optional<Employee> mostRecent = employees.stream()
            .max(Comparator.comparing(Employee::getJoinDate));

        mostRecent.ifPresent(e ->
            System.out.println("Most recent: " + e.getName()
                + " joined " + e.getJoinDate()));
    }
}
TEXT
Most recent: Meera joined 2024-07-20

How do you find the earliest joiner?

JAVA
Optional<Employee> earliest = employees.stream()
    .min(Comparator.comparing(Employee::getJoinDate));

earliest.ifPresent(e ->
    System.out.println("Earliest: " + e.getName()
        + " joined " + e.getJoinDate()));
TEXT
Earliest: Suresh joined 2005-04-01

How do you find the most recent joiner per department?

JAVA
Map<String, Optional<Employee>> recentPerDept = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDepartment,
        Collectors.maxBy(Comparator.comparing(Employee::getJoinDate))));

recentPerDept.forEach((dept, opt) ->
    opt.ifPresent(e ->
        System.out.println(dept + ": " + e.getName()
            + " (" + e.getJoinDate() + ")")));

How do you handle null join dates?

JAVA
// WRONG: NullPointerException if joinDate is null
Optional<Employee> wrong = employees.stream()
    .max(Comparator.comparing(Employee::getJoinDate));

// CORRECT: filter nulls first
Optional<Employee> correct = employees.stream()
    .filter(e -> e.getJoinDate() != null)
    .max(Comparator.comparing(Employee::getJoinDate));

// CORRECT: use nullsFirst/nullsLast
Optional<Employee> withNulls = employees.stream()
    .max(Comparator.comparing(Employee::getJoinDate,
        Comparator.nullsFirst(Comparator.naturalOrder())));

What is the difference between max(comparing(date)) and sorted().findFirst()?

| Approach | Time complexity | Short-circuits? | Result |
|---|---|---|---|
| max(comparing(date)) | O(n) single pass | No | Optional |
| sorted(date.reversed()).findFirst() | O(n log n) sort | Yes after first | Optional |

max is O(n) because it scans once. sorted().findFirst() sorts the entire stream first, which is O(n log n). Use max for finding a single extreme value.

What are common mistakes?

Mistake: confusing max and min for dates.

JAVA
// WRONG: min gives the EARLIEST date, not the most recent
Optional<Employee> wrong = employees.stream()
    .min(Comparator.comparing(Employee::getJoinDate));
// This is Suresh (2005), not Meera (2024)!

// CORRECT: max gives the LATEST (most recent) date
Optional<Employee> correct = employees.stream()
    .max(Comparator.comparing(Employee::getJoinDate));

What are common interview follow-up questions?

  • "How do you find the 3 most recent joiners?" Use sorted(comparing(joinDate).reversed()).limit(3).
  • "How do you find who joined in the same month as the most recent joiner?" First find the max date, then filter by its month.
  • "What if two employees joined on the same day?" max returns the first one in encounter order. Use thenComparing(name) for deterministic tie-breaking.

Visual Overview

DIAGRAM
  Stream<Employee>  (with join dates)
  [2015-03, 2021-06, 2005-04, 2022-03, 2024-07, ...]
       │
       │  .max(comparing(getJoinDate))
       ▼
  Scans all elements, tracks latest date:
    2015-03 → current max = 2015-03
    2021-06 → current max = 2021-06 (later)
    2005-04 → current max = 2021-06 (earlier, skip)
    2022-03 → current max = 2022-03 (later)
    2024-07 → current max = 2024-07 (later)
       │
       ▼
  Optional[Meera, 2024-07-20]  ← most recent

Key Takeaway

Finding the most recent joiner uses max(Comparator.comparing(Employee::getJoinDate)) because the latest date is the maximum in chronological order. LocalDate implements Comparable, so the natural ordering comparator works directly.

For per-department most recent, combine with groupingBy: groupingBy(dept, maxBy(comparing(joinDate))). For the earliest joiner, swap max for min.

The max approach is O(n), scanning once. The alternative sorted().findFirst() is O(n log n) because it sorts first. Always prefer max for a single extreme.

Remember one sentence: max with comparing(joinDate) finds the most recent joiner in O(n), and min finds the earliest.

---

Share
Use ← → arrow keys to navigate