Definition
Comparator.comparing(Employee::getSalary).reversed()builds ascending, then flips to descending.reversed()wraps the comparator and negates its result.comparingDoubleis the boxing-free equivalent fordoublekeys.- BigDecimal:
Comparator.comparingworks directly because BigDecimal implements Comparable. - Both produce the same order; the only difference is boxing overhead.
At the National Bank of India, Priya wants the richest-first payroll list. comparing(salary) sorts smallest to largest, and .reversed() turns it upside down.
Understanding the Concepts
How does comparing versus comparingDouble matter?
package com.bank.hr;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
public class ComparingVsComparingDouble {
public static void main(String[] args) {
List<Employee> staff = List.of(
new Employee("Rajesh", "Loans", new BigDecimal("95000")),
new Employee("Priya", "IT", new BigDecimal("120000")),
new Employee("Amit", "Finance", new BigDecimal("85000")));
// With BigDecimal (exact, no boxing issue)
List<Employee> byBigDecimal = staff.stream()
.sorted(Comparator.comparing(Employee::getSalary).reversed())
.collect(Collectors.toList());
byBigDecimal.forEach(e -> System.out.printf("%s - Rs. %s%n",
e.getName(), e.getSalary().toPlainString()));
}
}
Priya - Rs. 120000
Rajesh - Rs. 95000
Amit - Rs. 85000
What is the difference between comparing and comparingDouble?
| Method | Key type | Boxing | When to use |
|---|---|---|---|
| comparing(getSalary) | BigDecimal (object) | No boxing needed | When salary is BigDecimal |
| comparing(getSalaryAsDouble) | Double (boxed) | Yes, boxes each double | Avoid |
| comparingDouble(getSalaryAsDouble) | double (primitive) | No boxing | When salary is primitive double |
// For primitive double salary (not recommended for real money)
staff.stream()
.sorted(Comparator.comparingDouble(Employee::getSalaryAsDouble).reversed())
.collect(Collectors.toList());
// For BigDecimal salary (recommended)
staff.stream()
.sorted(Comparator.comparing(Employee::getSalary).reversed())
.collect(Collectors.toList());
What does reversed() do internally?
reversed() returns a new comparator that wraps the original. When comparing two elements, it calls the original comparator and negates the result. If the original returns -1 (a < b), reversed returns +1 (a > b).
What are common mistakes?
Mistake: using double for money instead of BigDecimal.
// WRONG: double loses precision for many decimal amounts
double salary = 95000.10;
// May not be exactly 95000.10 in memory
// CORRECT: BigDecimal is exact
BigDecimal salary = new BigDecimal("95000.10");
What about NaN values with comparingDouble?
If any salary is Double.NaN, comparingDouble places it inconsistently in the sort because NaN is not ordered. Always validate data before sorting.
What should a senior engineer know?
- Real balances should be
BigDecimal, notdouble, because double cannot represent many decimal amounts exactly. - With BigDecimal,
Comparator.comparing(Employee::getSalary)works directly because BigDecimal implements Comparable. reversed()is a decorator: it wraps the original comparator and negates its verdict.- Both comparing and comparingDouble produce identical ordering; the difference is purely about boxing overhead.
What are common interview follow-up questions?
- "Why not use double for money?" double is imprecise for many decimal fractions.
- "What does reversed do?" Negates the comparator's result.
- "When does comparingDouble matter?" When the field is a primitive double, to avoid boxing.
Visual Overview
Comparator.comparing(Employee::getSalary)
┌──────────────────────────────────────────┐
│ Amit(85000) < Rajesh(95000) < Priya(120000) │ ← ascending
└──────────────────────────────────────────┘
│
│ .reversed()
▼
┌──────────────────────────────────────────┐
│ Priya(120000) > Rajesh(95000) > Amit(85000) │ ← descending
└──────────────────────────────────────────┘
Key Takeaway
To sort by salary descending I build the ascending comparator and call .reversed(), which negates every comparison result. For BigDecimal salary, Comparator.comparing(Employee::getSalary) works directly because BigDecimal is Comparable with exact compareTo.
The nuance is comparing versus comparingDouble. If salary is a primitive double, comparingDouble avoids boxing each value into a Double. But for real money I always use BigDecimal, where comparing works without any boxing concern.
In my banking project at the National Bank of India this generated the payroll report with highest earners first.
Remember one sentence: comparing(salary).reversed() gives descending order, and for real money always use BigDecimal so the comparison is exact.
---