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 signifiesobj1
is less thanobj2
, zero indicates equality, and a positive value meansobj1
is greater thanobj2
.equals(Object obj)
: Inherited from theObject
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.