Java Tutorial 0/145 lessons ~6 min read Lesson 34

    Java Comparator & Comparable

    java Comparator Comparable compareTo compare Collections.sort TimSort thenComparing reversed

    Course progress0%
    Focus
    36 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Learning Objectives

    After completing this lesson, you will be able to:

    • Understand why sorting is important in Java
    • Learn the difference between Comparable and Comparator
    • Implement natural ordering using Comparable
    • Implement custom sorting using Comparator
    • Sort objects using Collections and Streams
    • Use Lambda Expressions with Comparator
    • Learn Comparator utility methods
    • Understand sorting internals
    • Apply sorting in Spring Boot applications
    • Follow enterprise best practices
    • Prepare for Java interview questions

    Introduction

    Sorting is one of the most common operations in enterprise applications.

    Examples:

    • Sort employees by salary
    • Sort products by price
    • Sort students by marks
    • Sort orders by date
    • Sort customers by name
    • Sort transactions by amount
    • Sort logs by timestamp
    • Sort flights by departure time

    Java provides two mechanisms for sorting objects:

    • Comparable
    • Comparator

    Both are extensively used in:

    • Collections Framework
    • Streams API
    • Spring Boot
    • Hibernate
    • JavaFX
    • Enterprise Applications

    Why Comparable & Comparator?

    Suppose we have an Employee class.

    code
    public class Employee {
    private int id;
    private String name;
    private double salary;
    }

    Now suppose we have:

    code
    List<Employee> employees = ...

    How should Java sort these employees?

    • By ID?
    • By Name?
    • By Salary?
    • By Joining Date?

    Java needs a way to know the sorting logic.

    This is where Comparable and Comparator come into the picture.

    Comparable vs Comparator

    ComparableComparator
    Package: java.langPackage: java.util
    Natural OrderingCustom Ordering
    Inside the classOutside the class
    One sorting strategyMultiple sorting strategies
    Implements compareTo()Implements compare()

    Sorting Architecture

    code
    List<Employee>
    ┌─────────────┴─────────────┐
    │ │
    Comparable Comparator
    │ │
    Natural Sorting Custom Sorting

    What is Comparable?

    Comparable defines the natural ordering of objects.

    Interface

    code
    public interface Comparable<T>{
    int compareTo(T object);
    }

    Implementing Comparable

    code
    public class Employee
    implements Comparable<Employee>{
    private int id;
    private String name;
    @Override
    public int compareTo(Employee other){
    return this.id - other.id;
    }
    }

    Sorting using Comparable

    code
    List<Employee> employees =
    new ArrayList<>();
    Collections.sort(employees);

    Java automatically calls:

    code
    compareTo()

    Example Output

    Before Sorting

    code
    102 Rahul
    101 Amit
    103 John

    After Sorting

    code
    101 Amit
    102 Rahul
    103 John

    compareTo() Return Values

    code
    this.compareTo(other)
    Return ValueMeaning
    NegativeCurrent object is smaller
    ZeroEqual
    PositiveCurrent object is greater

    Example

    code
    return this.salary.compareTo(other.salary);

    What is Comparator?

    Comparator allows multiple custom sorting strategies.

    Interface

    code
    public interface Comparator<T>{
    int compare(T o1, T o2);
    }

    Sorting by Name

    code
    public class NameComparator
    implements Comparator<Employee>{
    @Override
    public int compare(
    Employee e1,
    Employee e2){
    return e1.getName()
    .compareTo(
    e2.getName());
    }
    }

    Usage

    code
    Collections.sort(
    employees,
    new NameComparator()
    );

    Sorting by Salary

    code
    public class SalaryComparator
    implements Comparator<Employee>{
    @Override
    public int compare(
    Employee e1,
    Employee e2){
    return Double.compare(
    e1.getSalary(),
    e2.getSalary());
    }
    }

    Comparator using Lambda

    Java 8 simplified sorting.

    code
    employees.sort(
    (a,b) ->
    Double.compare(
    a.getSalary(),
    b.getSalary()
    )
    );

    Comparator using Method Reference

    code
    employees.sort(
    Comparator.comparing(
    Employee::getName
    )
    );

    Reverse Sorting

    code
    employees.sort(
    Comparator
    .comparing(
    Employee::getSalary
    )
    .reversed()
    );

    Multiple Field Sorting

    Sort by Department, then Salary.

    code
    employees.sort(
    Comparator
    .comparing(Employee::getDepartment)
    .thenComparing(Employee::getSalary)
    );

    Comparator Utility Methods

    Java provides many helper methods.

    comparing()

    code
    Comparator.comparing(
    Employee::getName
    );

    reversed()

    code
    Comparator
    .comparing(
    Employee::getSalary
    )
    .reversed();

    thenComparing()

    code
    Comparator
    .comparing(Employee::getDepartment)
    .thenComparing(Employee::getName);

    nullsFirst()

    code
    Comparator.nullsFirst(
    Comparator.naturalOrder()
    );

    nullsLast()

    code
    Comparator.nullsLast(
    Comparator.naturalOrder()
    );

    Sorting using Streams

    code
    employees.stream()
    .sorted(
    Comparator.comparing(
    Employee::getSalary
    )
    )
    .forEach(System.out::println);

    Comparable vs Comparator Example

    Comparable

    code
    Employee
    Sort by Employee ID

    Comparator

    code
    Employee
    Sort by Salary
    Sort by Name
    Sort by Department
    Sort by Experience

    Internal Working

    code
    Collections.sort()
    TimSort Algorithm
    compareTo()/compare()
    Sorted Collection

    Java uses TimSort, a hybrid sorting algorithm derived from Merge Sort and Insertion Sort.

    Complexity

    CaseComplexity
    BestO(n)
    AverageO(n log n)
    WorstO(n log n)

    Real-World Example: Employee Management

    code
    employees.sort(
    Comparator
    .comparing(Employee::getDepartment)
    .thenComparing(Employee::getSalary)
    .reversed()
    );

    Real-World Example: Product Sorting

    code
    products.sort(
    Comparator
    .comparing(Product::getPrice)
    );

    Real-World Example: Student Ranking

    code
    students.sort(
    Comparator
    .comparing(Student::getMarks)
    .reversed()
    );

    Spring Boot Example

    Repository

    code
    List<Employee> employees =
    repository.findAll();

    Sorting

    code
    employees.sort(
    Comparator
    .comparing(Employee::getJoiningDate)
    );

    Best Practices

    Use Comparable for Natural Ordering

    Example

    • Employee ID
    • Roll Number
    • Account Number

    Use Comparator for Business Rules

    Example

    • Salary
    • Department
    • Name
    • Joining Date

    Prefer Comparator.comparing()

    Cleaner than manually implementing compare().

    Use Lambda Expressions

    Prefer concise lambda expressions over anonymous classes.

    Avoid Subtraction for Integer Comparison

    Instead of

    code
    return a - b;

    Use

    code
    return Integer.compare(a,b);

    This avoids integer overflow.

    Chain Comparisons

    Use thenComparing() instead of nested if-else blocks.

    Common Mistakes

    Returning Incorrect Values

    Wrong

    code
    return 1;

    Always implement consistent comparison logic.

    Using == for Strings

    Wrong

    code
    name1 == name2

    Correct

    code
    name1.compareTo(name2)

    or

    code
    Objects.equals(name1, name2)

    depending on the requirement.

    Ignoring Null Values

    Use

    code
    Comparator.nullsFirst()

    or

    code
    Comparator.nullsLast()

    Violating compareTo() Contract

    Ensure comparisons are:

    • Consistent
    • Symmetric
    • Transitive

    Multiple Comparable Implementations

    A class can implement only one natural ordering. Use Comparators for additional sorting strategies.

    Hands-on Exercise

    Create a Java program that:

    1. Creates an Employee class implementing Comparable.
    2. Sorts employees by ID.
    3. Creates a SalaryComparator.
    4. Creates a NameComparator.
    5. Sorts using Lambda expressions.
    6. Uses Comparator.comparing().
    7. Uses thenComparing().
    8. Uses reversed().
    9. Uses nullsFirst().
    10. Sorts employees using the Streams API.

    Summary

    Comparable and Comparator provide the foundation for sorting in Java. Comparable defines a class's natural ordering, while Comparator enables multiple custom sorting strategies. Modern Java encourages using Comparator.comparing(), lambda expressions, and method references to build concise, readable, and maintainable sorting logic. These APIs are heavily used in enterprise applications, especially with Collections, Streams, Spring Boot, and data processing.

    Key Takeaways

    • Comparable defines natural ordering.
    • Comparator defines custom ordering.
    • compareTo() belongs to Comparable.
    • compare() belongs to Comparator.
    • Use Comparator.comparing() for clean code.
    • Use thenComparing() for multi-level sorting.
    • Use reversed() for descending order.
    • Handle null values with nullsFirst() and nullsLast().
    • Streams integrate seamlessly with Comparator.
    • Java uses TimSort for sorting object collections.

    Professional Interview Questions

    1What is the difference between Comparable and Comparator?

    Professional Answer

    Comparable is used to define the natural ordering of a class and requires implementing the compareTo() method within the class itself. Comparator is used to define external, customizable sorting logic through the compare() method, allowing multiple sorting strategies for the same class without modifying its source code.

    Follow-up Questions

    • Which package contains Comparable?
    • Can a class have multiple Comparator implementations?
    • Can a class implement more than one Comparable?

    Interview Tip: Comparable → Natural Order, Comparator → Custom Order.

    2Why should Integer.compare() or Double.compare() be preferred over subtraction?

    Professional Answer

    Using subtraction, such as return a - b, can lead to integer overflow when comparing very large or very small values. Methods like Integer.compare(), Long.compare(), and Double.compare() provide safe, readable, and overflow-free comparisons, making them the recommended approach in production code.

    Follow-up Questions

    • Can subtraction cause incorrect sorting?
    • Which compare method should be used for floating-point values?

    Interview Tip: Always prefer Integer.compare(), Long.compare(), Double.compare() instead of arithmetic subtraction.

    3What sorting algorithm does Collections.sort() use?

    Professional Answer

    Since Java 7, Collections.sort() and List.sort() use TimSort, a hybrid sorting algorithm derived from Merge Sort and Insertion Sort. TimSort is stable, performs exceptionally well on partially sorted data, and has a worst-case time complexity of O(n log n), making it suitable for enterprise applications.

    Follow-up Questions

    • Is TimSort a stable sorting algorithm?
    • What is its average time complexity?
    • Does Arrays.sort() always use TimSort?

    Interview Tip: Objects (Collections.sort, List.sort) → TimSort, Primitive arrays (Arrays.sort(int[])) → Dual-Pivot QuickSort.

    Ready to mark this lesson complete?Track your journey across the entire course.