Java ProgramsCollectionsSort Objects Using Comparator

Sort Objects Using Comparator in Java

beginner·  Collections  ·  Comparator & Comparable

Problem

A Comparator defines sorting logic from outside the class being sorted, so a class doesn't need to implement Comparable itself just to be sortable one particular way.

Given a list of Employee objects, sort them by salary using a Comparator instead of modifying the Employee class.

Input
Alice (55000.0), Bob (42000.0), Charlie (61000.0), sorted by salary
Output
Bob: 42000.0 Alice: 55000.0 Charlie: 61000.0

Java Program

Java
import java.util.ArrayList; import java.util.List; class Employee { String name; double salary; Employee(String name, double salary) { this.name = name; this.salary = salary; } } public class SortObjectsUsingComparator { public static void main(String[] args) { List<Employee> employees = new ArrayList<>(); employees.add(new Employee("Alice", 55000.0)); employees.add(new Employee("Bob", 42000.0)); employees.add(new Employee("Charlie", 61000.0)); employees.sort((a, b) -> Double.compare(a.salary, b.salary)); // external comparison rule for (Employee e : employees) { System.out.println(e.name + ": " + e.salary); } } }

Output

Bob: 42000.0 Alice: 55000.0 Charlie: 61000.0

Core Logic

Passing a lambda that compares two Employee objects by their salary field directly to sort() supplies the ordering rule without Employee ever needing to implement Comparable.

How It Works
  1. 1Employee is a plain class with name and salary fields — it implements no sorting-related interface at all.
  2. 2employees.sort((a, b) -> Double.compare(a.salary, b.salary)) passes a lambda that compares two employees purely by salary.
  3. 3Double.compare() returns negative, zero, or positive depending on which salary is smaller, larger, or equal — exactly what sort() needs to order the list.
  4. 4The list is sorted in place; no new list is created.
Sorting [Alice(55000), Bob(42000), Charlie(61000)] by salary produces [Bob, Alice, Charlie], ascending.
💡

Key Point: Because the Comparator lives outside Employee, the exact same objects could be sorted a completely different way elsewhere — by name, for instance — just by passing a different lambda, without touching the Employee class at all.

Complexity
Time Complexity: O(n log n)Space Complexity: O(n)

Why: List.sort() uses a merge-based algorithm (TimSort) for object lists, which does O(n log n) comparisons and needs a temporary array of size proportional to n for merging.

Key Concepts

Comparatorlambda expressionlist.sort()

Approach 2: Java 8

Java
import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; class EmployeeRecord { String name; double salary; EmployeeRecord(String name, double salary) { this.name = name; this.salary = salary; } } public class SortObjectsUsingComparatorStream { public static void main(String[] args) { List<EmployeeRecord> employees = List.of( new EmployeeRecord("Alice", 55000.0), new EmployeeRecord("Bob", 42000.0), new EmployeeRecord("Charlie", 61000.0) ); // Sorts by the extracted salary key, collecting into a new list List<EmployeeRecord> sorted = employees.stream() .sorted(Comparator.comparingDouble(e -> e.salary)) .collect(Collectors.toList()); for (EmployeeRecord e : sorted) { System.out.println(e.name + ": " + e.salary); } } }

Output

Bob: 42000.0 Alice: 55000.0 Charlie: 61000.0

Core Logic

Sorting the stream with Comparator.comparingDouble() and collecting the result expresses the same salary-based ordering as a pipeline, using a purpose-built comparator factory instead of a hand-written lambda.

How It Works
  1. 1employees.stream() opens a stream over the list's elements.
  2. 2Comparator.comparingDouble(e -&gt; e.salary) builds a comparator from a key-extractor function, replacing the manual (a, b) -&gt; Double.compare(a.salary, b.salary) lambda with an equivalent, more declarative expression.
  3. 3.sorted(...) applies that comparator to produce a new, sorted stream, leaving the original list untouched.
  4. 4.collect(Collectors.toList()) gathers the sorted stream into a new List.
  5. 5Unlike the primary approach's in-place sort(), this produces a separate sorted list rather than reordering employees itself.
Streaming and sorting [Alice(55000), Bob(42000), Charlie(61000)] by salary collects into [Bob, Alice, Charlie], the same ascending order the primary approach produces.
💡

Key Point: Comparator.comparingDouble() (and its comparingInt()/comparing() siblings) reads as 'sort by this key', which is often clearer than a raw comparison lambda once the sort key is just a single field.

Complexity
Time Complexity: O(n log n)Space Complexity: O(n)

Why: sorted() still performs the same comparison-based sort as List.sort(), and collect() additionally builds a new list to hold the result, unlike the primary approach's in-place sort.

Key Concepts

StreamComparator.comparingDouble()Collectors.toList()

Related Programs