Comparable, Comparator and compareTo in Java

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).

Java
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).

Java
@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.

Java
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

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.

Java
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.

Java
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.

Java
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

Java
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.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.