RadhaPublication
HomeInterviewLearning PathsRole TracksMockBooksPricing
Login / Sign UpLog in

© 2026 Radha Publication. All rights reserved.

Shop on AmazonDonateContactPrivacyTerms
Java questions
MediumJava#927 min readJul 11, 2026

Sort Employees by salary.

practice
learning
Practice modeTest yourself instead of reading straight through

Hook: Interviewers love this one because it checks whether you can turn a plain-English request into a safe Java comparator without creating money bugs.

Question: How do I sort a list of Employee objects by salary in Java?

Answer: Create a Comparator that compares the salary field, then pass it to List.sort(...) or Collections.sort(...). If salary is real money, prefer BigDecimal instead of double so you avoid floating-point rounding errors. If two salaries are equal, add a tie-breaker such as name so the result is predictable.

Interview-Ready Answer: I would sort the employees with a comparator on salary. In Java, I prefer List.sort(Comparator), and for money values I use BigDecimal rather than double. If salaries can match, I add a second rule like name as a tie-breaker, and because Java’s object sort is stable, equal items keep their original order unless I define more rules.

🧠 Memory Map
Memory map — visual summary of this topic

What you are really doing

Sorting employees by salary is not about moving objects around by hand. You are teaching Java one simple rule: when it compares two employees, which one should come first?

  1. Pick the salary type. For interviews, BigDecimal is the safest choice for money because it avoids floating-point rounding mistakes.
  2. Write a Comparator. A comparator is a small object that says before, same, or after when it looks at two employees.
  3. Decide how to handle messy data. If the list can contain null, or if salary can be null, use Comparator.nullsLast(...) or nullsFirst(...).
  4. Add a tie-breaker with thenComparing. This is useful when two employees have the same salary and you still want a deterministic order.
  5. Call employees.sort(comparator). This sorts the list in place, meaning the original list is changed.
  6. Read the result. Equal keys keep their relative order because Java uses a stable sort for object sorting.

Why this works under the hood

Java does not need your salary field to be the first field in the class or to implement special interfaces manually. It just needs a rule that can compare two values consistently. For object sorting, Java uses a stable algorithm called TimSort. Stable means if two items compare as equal, their original order stays the same. That matters when employees have the same salary and you do not want the display order to jump around between runs.

Comparison of common Java sort choices

MethodMutates?Best forNote
List.sortYesModern codeSimple and readable
Collections.sortYesLegacy codeStill fine, just older style
Stream.sortedNoNeed a new listReturns a sorted stream, then collect it

Performance and interview details

For object sorting, expect about O(n log n) time in the general case. On a list of 1,000,000 employees, that means roughly 20 million compare steps in the rough mental model. Extra memory can go up to O(n) because Java may need temporary storage while sorting object data. If the list is already partly sorted, TimSort can do even better in practice.

Two important gotchas:

  • Do not subtract salaries in a comparator like a - b. That can overflow for large numbers, and it is wrong for money stored as decimal values.
  • Do not sort money as strings. String order would place 100000 before 9000 because it compares characters, not numeric value.

When and why to use it

Use salary sorting in dashboards, payroll exports, compensation review screens, and reporting jobs. If the list is only for display, Stream.sorted() is nice because it returns a new sequence. If you need to update the same list object already held in memory, List.sort() is the cleanest choice.

Memory rule: think of the comparator as the referee. It never moves the players; it only decides who stands in front, who stands behind, and who is a tie.

Real-World Story: In a payroll or HR compensation dashboard, managers often sort employees by salary descending to find the highest-paid people quickly. The backend usually sends a list to the UI, and the UI may let users switch between ascending and descending views. If the sort logic is wrong, the whole screen can look trustworthy while quietly showing the wrong ranking.

Here is a common incident: a team stored salary as a decimal number but wrote a comparator using subtraction and then cast the result to int. For very close salaries, the comparison returned 0, so different employees appeared in random order. Managers complained that the top-10 list changed after every refresh, audit exports did not match the dashboard, and support tickets mentioned salary order is unstable. The fix was to use a proper comparator, keep salary as BigDecimal, and add a tie-breaker so equal salaries always sort the same way.

What users would notice:

  • The ranking jumps after refresh.
  • CSV exports disagree with the page view.
  • Logs may show no exception, which makes the bug feel mysterious.
  • Finance or HR reviewers lose trust in the data.
Java
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class SortEmployeesBySalary {
    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("Ava", new BigDecimal("95000.00")));
        employees.add(new Employee("Noah", new BigDecimal("120000.00")));
        employees.add(new Employee("Mia", new BigDecimal("95000.00"))); // same salary as Ava
        employees.add(new Employee("Zoe", null)); // missing salary edge case
        employees.add(null); // dirty data edge case

        // BigDecimal avoids floating-point rounding bugs that can break salary order.
        // The tie-breaker keeps the result deterministic when salaries match.
        Comparator<Employee> bySalaryAscending = Comparator.nullsLast(
                Comparator.comparing(
                        Employee::getSalary,
                        Comparator.nullsLast(Comparator.naturalOrder())
                ).thenComparing(
                        Employee::getName,
                        Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER)
                )
        );

        Comparator<Employee> bySalaryDescending = Comparator.nullsLast(
                Comparator.comparing(
                        Employee::getSalary,
                        Comparator.nullsLast(Comparator.reverseOrder())
                ).thenComparing(
                        Employee::getName,
                        Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER)
                )
        );

        System.out.println("Ascending by salary:");
        employees.sort(bySalaryAscending);
        printEmployees(employees);

        System.out.println("\nDescending by salary:");
        employees.sort(bySalaryDescending);
        printEmployees(employees);
    }

    private static void printEmployees(List<Employee> employees) {
        for (Employee employee : employees) {
            if (employee == null) {
                System.out.println("null employee");
            } else {
                System.out.println(employee);
            }
        }
    }

    static class Employee {
        private final String name;
        private final BigDecimal salary;

        Employee(String name, BigDecimal salary) {
            this.name = name;
            this.salary = salary;
        }

        public String getName() {
            return name;
        }

        public BigDecimal getSalary() {
            return salary;
        }

        @Override
        public String toString() {
            return name + " -> " + (salary == null ? "null" : salary.toPlainString());
        }
    }
}

Follow-up & Tricky Questions:

  • How do you sort by salary descending? Use a descending comparator, for example Comparator.reverseOrder() for comparable values or reversed() on a comparator. For money, I prefer building the descending rule directly so null handling and tie-breakers stay clear.
  • How do you break ties when salaries are equal? Use thenComparing, such as salary first and name second. That makes the order deterministic instead of depending on the original list order alone.
  • What if salary can be null? Wrap the salary comparator in Comparator.nullsLast(...) or nullsFirst(...). That prevents NullPointerException and gives you an explicit business rule.
  • Does the sort change the original list? Yes, List.sort sorts the same list object in place. If you want a new sorted list, use stream().sorted(...) and collect the result.
  • Is Java sorting stable here? Yes, for object sorting Java uses a stable algorithm, so equal salaries keep their relative order unless you add tie-breakers.
  • Why is BigDecimal better than double for salary? BigDecimal stores decimal values exactly enough for money calculations, while double can introduce tiny binary rounding errors that break comparisons and totals.
  • Why not use a.salary - b.salary? That is unsafe for large numbers and incorrect for decimal money. The comparator contract also expects clean comparison logic, not arithmetic subtraction.
  • What happens if the comparator returns 0 for different employees? Java treats them as equal for ordering, so a stable sort keeps their original order. If that is not what you want, add a tie-breaker field.

Tricky / Gotcha Questions:

  • Can I sort salaries stored as strings? You can, but you should convert them to numbers or BigDecimal first. String sorting compares text, not numeric size, so the order can be wrong.
  • Is Collections.sort better than List.sort? Not really; both sort in place. List.sort is the modern instance method and usually reads better in new code.
  • Does reversed() always preserve null handling exactly the way I want? No, reversing a whole comparator can also reverse the placement of nulls. If null behavior matters, build the descending comparator explicitly instead of relying on a blanket reverse.

Common Mistakes:

  • Using subtraction to compare salaries. Correction: use Comparator.comparing(...), Integer.compare, Long.compare, or BigDecimal comparison methods.
  • Sorting money as double without thinking. Correction: prefer BigDecimal for currency so pennies do not disappear into rounding errors.
  • Forgetting tie-breakers. Correction: if equal salaries matter, chain thenComparing with name or id.
  • Ignoring nulls. Correction: decide the business rule up front and use nullsFirst or nullsLast.

Memory Hook: Think of salary sorting like a race scoreboard: salary is the finish time, and name is the photo-finish backup when two people cross together.

Cheat Sheet:

  • Use a Comparator on salary.
  • For money, use BigDecimal, not double.
  • Use List.sort to sort in place.
  • Add thenComparing for stable, deterministic ties.
  • Use nullsLast or nullsFirst if data can be missing.
  • Time: about O(n log n); object sort is stable.

Practice Tasks:

  • Sort a small employee list by salary ascending and print it.
  • Add descending order and a tie-breaker by employee id.
  • Make the list contain a null employee and a null salary, then keep the sort from failing.
Previous
Back to Questions←→to navigate
Next

Recommended Resources

Recommended Book

Cracking the Coding Interview

189 Programming Questions and Solutions

Recommended Book

Cracking the Coding Interview

189 Programming Questions and Solutions

import java.math.BigDecimal; import java.util.ArrayList; import java.util.Comparator; import java.util.List; public class SortEmployeesBySalary { public static void main(String[] args) { List<Employee> employees = new ArrayList<>(); employees.add(new Employee("Ava", new BigDecimal("95000.00"))); employees.add(new Employee("Noah", new BigDecimal("120000.00"))); employees.add(new Employee("Mia", new BigDecimal("95000.00"))); // same salary as Ava employees.add(new Employee("Zoe", null)); // missing salary edge case employees.add(null); // dirty data edge case // BigDecimal avoids floating-point rounding bugs that can break salary order. // The tie-breaker keeps the result deterministic when salaries match. Comparator<Employee> bySalaryAscending = Comparator.nullsLast( Comparator.comparing( Employee::getSalary, Comparator.nullsLast(Comparator.naturalOrder()) ).thenComparing( Employee::getName, Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER) ) ); Comparator<Employee> bySalaryDescending = Comparator.nullsLast( Comparator.comparing( Employee::getSalary, Comparator.nullsLast(Comparator.reverseOrder()) ).thenComparing( Employee::getName, Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER) ) ); System.out.println("Ascending by salary:"); employees.sort(bySalaryAscending); printEmployees(employees); System.out.println("\nDescending by salary:"); employees.sort(bySalaryDescending); printEmployees(employees); } private static void printEmployees(List<Employee> employees) { for (Employee employee : employees) { if (employee == null) { System.out.println("null employee"); } else { System.out.println(employee); } } } static class Employee { private final String name; private final BigDecimal salary; Employee(String name, BigDecimal salary) { this.name = name; this.salary = salary; } public String getName() { return name; } public BigDecimal getSalary() { return salary; } @Override public String toString() { return name + " -> " + (salary == null ? "null" : salary.toPlainString()); } } }