1. Comparable Interface:
In Java, Comparable
interface is used to define the ordering of objects. When a class implements Comparable
, it means that instances of that class can be compared to each other using the natural ordering defined in the compareTo
method. Here’s a step-by-step explanation with an example:
Example using Comparable:
Suppose we have a Employee
class, and we want to compare Employee based on their ages. To implement this using Comparable
, we follow these steps:
The Employee class implements the Comparable<Employee>
interface, specifying the type it can be compared to (Person
in this case).
class Employee implements Comparable<Employee> {
// ...
}
Within the Person
class, we implement the compareTo
method. This method compares the current instance (this) with another instance (other
) based on a chosen criteria (in this case, age).
@Override
public int compareTo(Employee other) {
// Compare based on age
return Integer.compare(this.age, other.age);
}
The compareTo
method returns a negative integer, zero, or a positive integer, depending on whether the current instance is less than, equal to, or greater than the other instance. In this case, we use Integer.compare
to compare the ages.
Now, when you have a list of Employee objects and you call Collections.sort(emp)
, the sorting operation will be based on the natural ordering defined by the compareTo
method, which is age in ascending order.
List<Employee> emp = new ArrayList<>();
emp.add(new Employee(23,"prakash1"));
emp.add(new Employee(43,"prakash2"));
emp.add(new Employee(13,"prakash3"));
Collections.sort(emp); // Sorts by age in ascending order
Here The full Program in Java
import java.util.*;
class Employee implements Comparable<Employee>{
int age;
String name;
Employee(int age, String name){
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public int compareTo(Employee emp){
return Integer.compare(this.age, emp.age);
}
@Override
public String toString() {
return "Employee{name='" + name + "', age=" + age + '}';
}
}
public class Main
{
public static void main(String[] args) {
List<Employee> emp = Arrays.asList(new Employee(23,"prakash1"), new Employee(43,"prakash2"), new Employee(13,"prakash3"));
Collections.sort(emp);
emp.stream().forEach(s->System.out.println(s.getName()));
for(Employee e : emp)
System.out.println(e);
}
}
Output
prakash3 prakash1 prakash2 Employee{name='prakash3', age=13} Employee{name='prakash1', age=23} Employee{name='prakash2', age=43}
2. Comparator Interface
In other hand, Comparator
interface allows you to define custom comparison logic for classes. You can control your sorting rule. Here’s a step-by-step explanation with an example:
Example using Comparator:
Suppose we have a Employee class again, but this time we want to compare employee based on their names. To implement this using a Comparator
, follow these steps:
We do not modify the Person
class itself, it remains without implementing Comparable
.
class Employee {
// ...
}
We define a custom Comparator<Person>
that specifies how Person
objects should be compared based on names. This is done externally to the Person
class.
Comparator<Employee> nameComparator = Comparator.comparing(Employee::getName);
Comparator.comparing
is a convenient way to create a Comparator
based on a specific attribute or method of the class. In this case, we’re comparing Person
objects based on their names.
Now, when you have a list of Employee objects and you want to sort them by name, you can use this Comparator
with Collections.sort
.
List<Employee> emp= new ArrayList<>();
emp.add(new Person("Alice", 25));
emp.add(new Person("Bob", 30));
emp.add(new Person("Charlie", 20));
Collections.sort(emp, nameComparator); // Sorts by name in alphabetical order
Complete Program
import java.util.*;
class Employee{
int age;
String name;
Employee(int age, String name){
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Employee{name='" + name + "', age=" + age + '}';
}
}
public class Main
{
public static void main(String[] args) {
List<Employee> emp = Arrays.asList(new Employee(23,"prakash8"), new Employee(43,"prakash2"), new Employee(13,"prakash3"));
Comparator<Employee> nameComparator = Comparator.comparing(Employee::getName);
Collections.sort(emp,nameComparator);
for(Employee e : emp)
System.out.println(e);
//using java8
emp.stream().sorted(Comparator.comparing(s->s.getName())).forEach(s->System.out.println(s.getName()));
}
}
In summary:
Comparable
is used when you want to define the natural ordering of objects within the class itself. It’s typically used when you have control over the class or when the ordering is the same across all contexts.Comparator
is used when you want to define custom ordering externally to the class. It’s helpful when you need different sorting criteria in different situations or when you don’t have control over the class’s implementation.