Java tutorials > Core Java Fundamentals > Data Structures and Collections > Difference between `Comparable` and `Comparator`?
Difference between `Comparable` and `Comparator`?
Introduction: Comparable vs. Comparator
Comparable Interface
public interface Comparable<T> {
int compareTo(T o);
}
Example of Comparable
class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Student other) {
return this.name.compareTo(other.name); // Natural ordering based on name
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args) {
Student s1 = new Student("Alice", 20);
Student s2 = new Student("Bob", 22);
Student s3 = new Student("Charlie", 19);
List<Student> students = new ArrayList<>();
students.add(s1);
students.add(s2);
students.add(s3);
Collections.sort(students); // Sorts based on the compareTo method
System.out.println(students); // Output: [Student{name='Alice', age=20}, Student{name='Bob', age=22}, Student{name='Charlie', age=19}]
}
}
Comparator Interface
public interface Comparator<T> {
int compare(T o1, T o2);
}
Example of Comparator
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return Integer.compare(s1.getAge(), s2.getAge()); // Compare based on age
}
}
public class Main {
public static void main(String[] args) {
Student s1 = new Student("Alice", 20);
Student s2 = new Student("Bob", 22);
Student s3 = new Student("Charlie", 19);
List<Student> students = new ArrayList<>();
students.add(s1);
students.add(s2);
students.add(s3);
Collections.sort(students, new AgeComparator()); // Sorts based on the AgeComparator
System.out.println(students); // Output: [Student{name='Charlie', age=19}, Student{name='Alice', age=20}, Student{name='Bob', age=22}]
}
}
Key Differences Summarized
When to use Comparable
When to use Comparator
Real-Life Use Case
Best Practices
Interview Tip
Alternatives
Pros of Comparable
Cons of Comparable
Pros of Comparator
Cons of Comparator
FAQ
-
What happens if a class implements both `Comparable` and I use a `Comparator`?
If you provide a `Comparator` to `Collections.sort` or a similar sorting method, the `Comparator` will take precedence over the natural ordering defined by `Comparable`. The `compareTo` method will be ignored. -
Is it mandatory to override `equals()` when implementing `Comparable`?
It's not strictly mandatory, but highly recommended. Consistency between `compareTo()` and `equals()` is crucial, especially when using sorted collections like `TreeSet` or `TreeMap`. If two objects are equal according to `equals()`, their `compareTo()` method should return 0. Failing to do so can lead to unexpected behavior where equal objects are treated as distinct by these collections. -
Can I use lambda expressions with `Comparator`?
Yes, you can definitely use lambda expressions with `Comparator` to create concise and readable comparators. For example:Comparator
This creates a `Comparator` that compares students based on their age using a lambda expression.ageComparator = (s1, s2) -> Integer.compare(s1.getAge(), s2.getAge());