How to Write a Comparator in Java

The Comparator interface in Java provides a way to define custom sorting logic for objects. This is crucial when you need to sort objects based on criteria other than their natural ordering (defined by the Comparable interface). This article will guide you through creating and using comparators in Java.

Understanding the Comparator Interface

The Comparator interface resides in the java.util package and declares two methods:

  • compare(Object obj1, Object obj2): Compares two objects and returns an integer indicating their order. A negative value signifies obj1 is less than obj2, zero indicates equality, and a positive value means obj1 is greater than obj2.
  • equals(Object obj): Inherited from the Object class, this method checks for object equality. It’s rarely used in the context of comparators.

When you want to sort objects of a class that doesn’t implement Comparable, or you need a different sorting order than the one provided by its natural ordering, you create a separate class that implements the Comparator interface.

Implementing a Comparator

Let’s consider a Student class with rollno and name fields. To sort students by rollno, we create a SortbyRoll class implementing Comparator:

import java.util.*;

class Student {
    int rollno;
    String name;

    Student(int rollno, String name) {
        this.rollno = rollno;
        this.name = name;
    }

    @Override
    public String toString() {
        return rollno + ": " + name;
    }
}

class SortbyRoll implements Comparator<Student> {
    public int compare(Student a, Student b) {
        return a.rollno - b.rollno; // Ascending order
    }
}

public class GFG {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student(111, "Mayank"));
        students.add(new Student(131, "Anshul"));
        students.add(new Student(121, "Solanki"));
        students.add(new Student(101, "Aggarwal"));

        Collections.sort(students, new SortbyRoll());

        System.out.println("Sorted by Roll Number ");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

This code snippet demonstrates how to define a custom comparator and use it with the Collections.sort() method to sort a list of Student objects in ascending order of their rollno. For descending order, simply reverse the subtraction in the compare method (return b.rollno - a.rollno;).

Using Lambda Expressions

Java 8 introduced lambda expressions, providing a more concise way to define comparators:

students.sort((p1, p2) -> Integer.compare(p1.rollno, p2.rollno));

This line achieves the same result as the SortbyRoll class, sorting students by rollno in ascending order using a lambda expression.

Sorting by Multiple Fields

To sort by multiple fields, chain comparisons within the compare method. For example, to sort students by name and then by age:

class Student {
    String name;
    int age;
    // ... constructor, getters ...
}


Collections.sort(students, Comparator.comparing(Student::getName).thenComparing(Student::getAge));

This sorts the students list first by name and then, if names are equal, by age. This approach utilizes the thenComparing method for cleaner, more readable code.

Comparator vs. Comparable

Feature Comparator Comparable
Definition External to the class Within the class
Sorting Logic Separate class or lambda compareTo() method
Flexibility Multiple sorting orders possible Single, natural sorting order

Choose Comparator for defining multiple sorting strategies or sorting objects of classes you don’t control. Use Comparable for defining a single, natural sorting order within the class itself. Understanding these differences allows you to leverage the power of both interfaces for efficient and customized object sorting in Java.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *