Comparable vs Comparator

One of the most common interview question is what is the difference between Comparator and Comparable ? Today we will get closer to the few main differences.

First thing to note that both are interfaces as some people considers Comparator as a Class by mistake. To be more clear about the comparable and comparator let’s have one small but quite meaningful example.

public class Person implements Comparable<Person> {
	
	private String name;
	
	private int age;

	public Person() {
		
	}
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public int compareTo(Person person) {
		//add null check to avoid null pointer
        if(person.getAge() > this.age) {
			return 1;
		} else if(person.getAge() < this.age) {
			return -1;
		} 
		return 0;
	}
	
	@Override
	public String toString() {
		return "Name :" + name + "- Age :" +age;
	}
	
}

In above method we have implemented the Comparable interface and so we have to implement method named compareTo of this interface. Mainly comparable is used for sorting, say you want to sort the Persons based on their age. It is worth to note that Collections.sort method uses this method to sort the elements, in other way you need to implement comparable to allow Collection.sort to sort your elements based on your compareTo method, let’s see how.

public class SortPersonsWithComparable {
	
	public static void main(String args[]) {
		Person person1 = new  Person("John", 23);
		Person person2 = new  Person("Martin", 78);
		Person person3 = new  Person("Frank", 13);
		
		List<Person> persons = new ArrayList<>();
		persons.add(person1);
		persons.add(person2);
		persons.add(person3);
		
		System.out.println("List of persons :" +persons);
		
		Collections.sort(persons);
		
		System.out.println("Sorted List of persons :" +persons);
		
	}
}

So in above example we have added three persons in the list and used Collection.sort for that list and we will have following output.

List of persons :[Name :John- Age :23, Name :Martin- Age :78, Name :Frank- Age :13]
Sorted List of persons :[Name :Martin- Age :78, Name :John- Age :23, Name :Frank- Age :13]

As you can see after sorting the elements we have list of person sorted with age.Now, let’s have an example of Comparator.

Comparator has compare(Object o1, Object o2) method which should return 1 if o1 > o2, 0 if o1 == o2 and -1 if o1 < o2 as you can see it compares two Objects and just take a look at comprable it compares one with other, quite a bit different. When you call person1.compareTo(person2) it simply means compare one person with other while compare(person1, person2) means compare two persons.

Note when we implement Comparator we have to implement compare method in that class and implementing compare in Person which compares two other person and not current (this) person, sounds weird. So what is the use of Comparator than ?

Comparator should be used in some other class to compare two other Objects. Whenever you want to sort a list based on custom comparison in some other class you should go with comparator. Let’s consider following examples,

public class SortPersonsWithComparator {
	
	public static void main(String args[]) {
		Person person1 = new  Person("John", 23);
		Person person2 = new  Person("Martin", 78);
		Person person3 = new  Person("Frank", 13);
		
		List<Person> persons = new ArrayList<>();
		persons.add(person1);
		persons.add(person2);
		persons.add(person3);
		
		System.out.println("List of persons :" +persons);
		//Add null checks whenever needed
		Collections.sort(persons, new Comparator<Person>() {

			@Override
			public int compare(Person o1, Person o2) {
				//Comparison based on length of names
				int length1 = o1.getName().length();
				int length2 = o2.getName().length();
				
				if(length1 > length2) {
					return 1;
				} else if(length1 < length2) {
					return -1;
				}
				return 0;
			}
		});
	
		System.out.println("Sort Based on length of Name :" + persons);
		
		Collections.sort(persons, new Comparator<Person>() {

			@Override
			public int compare(Person o1, Person o2) {
				if(o1.getAge() > o2.getAge()) {
					return 1;
				} else if(o1.getAge() < o2.getAge()) {
					return -1;
				}
				return 0;
			}
		});
	
		System.out.println("Sort Based on Age :" + persons);
	}
}

Note here we are comparing two other Objects in some other class which was not the case in comparable where we have declared comparable in Person class and sort internally invokes compareTo and we will have following output.

List of persons :[Name :John- Age :23, Name :Martin- Age :78, Name :Frank- Age :13]
Sort Based on length of Name :[Name :John- Age :23, Name :Frank- Age :13, Name :Martin- Age :78]
Sort Based on Age :[Name :Frank- Age :13, Name :John- Age :23, Name :Martin- Age :78]

comparable means compare this Person with PersonX and comparator means compare PersonA and PersonB in class C.

At first look we can not find this much different as both are actually used for comparison and mainly sorting purpose but from above examples we can say that we can have multiple implementations of Comparator in different classes based on requirements and a single implementation in the same class.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s