Home » Java » Core Java » Difference between Comparator and Comparable in Java

About Arpit Mandliya

Arpit Mandliya
I am java developer at Tata Consultancy Services Ltd. My current area of interest are J2EE,web development and java design patterns. I am technology enthusiast trying to explore new technologies. In spare time,I love blogging.

Difference between Comparator and Comparable in Java

One of the common interview question is ‘What are differences between Comparator and Comparable’. or ‘How will you sort collection of employee objects by its id or name’.For that we can use two interfaces.i.e. Comparator and Comparable.Before we actually see differences,let me give you brief introduction of both.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....

 

Comparable interface: Class whose objects to be sorted must implement this interface.In this,we have to implement compareTo(Object) method.

For example:

public class Country implements Comparable{
       @Override
    public int compareTo(Object arg0) {
        Country country=(Country) arg0;
        return (this.countryId < country.countryId ) ? -1: (this.countryId > country.countryId ) ? 1:0 ;
}}

If any class implements comparable inteface then collection of that object can be sorted automatically using Collection.sort() or Arrays.sort().Object will be sort on the basis of compareTo method in that class.

Objects which implement Comparable in java can be used as keys in a SortedMap like TreeMap or SortedSet like TreeSet without implementing any other interface.

Comparator interface: Class whose objects to be sorted do not need to implement this interface.Some third class can implement this interface to sort.e.g.CountrySortByIdComparator class can implement Comparator interface to sort collection of country object by id. For example:

public class CountrySortByIdComparator implements Comparator<Country>{

    @Override
    public int compare(Country country1, Country country2) {

        return (country1.getCountryId() < country2.getCountryId() ) ? -1: (country1.getCountryId() > country2.getCountryId() ) ? 1:0 ;
    }

}

Using Comparator interface,we can write different sorting based on different attributes of objects to be sorted.You can use anonymous comparator to compare at particular line of code. For example:

         Country indiaCountry=new Country(1, 'India');
         Country chinaCountry=new Country(4, 'China');
         Country nepalCountry=new Country(3, 'Nepal');
         Country bhutanCountry=new Country(2, 'Bhutan');

         List<Country> listOfCountries = new ArrayList<Country>();
         listOfCountries.add(indiaCountry);
         listOfCountries.add(chinaCountry);
         listOfCountries.add(nepalCountry);
         listOfCountries.add(bhutanCountry); 

 //Sort by countryName

            Collections.sort(listOfCountries,new Comparator<Country>() {

                @Override
                public int compare(Country o1, Country o2) {

                    return o1.getCountryName().compareTo(o2.getCountryName());
                }
            });

Comparator vs Comparable

ParameterComparableComparator
Sorting logicSorting logic must be in same class whose objects are being sorted. Hence this is called natural ordering of objectsSorting logic is in separate class. Hence we can write different sorting based on different attributes of objects to be sorted. E.g. Sorting using id,name etc.
ImplementationClass whose objects to be sorted must implement this interface.e.g Country class needs to implement comparable to collection of country object by idClass whose objects to be sorted do not need to implement this interface.Some other class can implement this interface. E.g.-CountrySortByIdComparator class can implement Comparator interface to sort collection of country object by id

Sorting method
int compareTo(Object o1)
This method compares this object with o1 object and returns a integer.Its value has following meaning
1. positive – this object is greater than o1
2. zero – this object equals to o1
3. negative – this object is less than o1
int compare(Object o1,Object o2)
This method compares o1 and o2 objects. and returns a integer.Its value has following meaning.
1. positive – o1 is greater than o2
2. zero – o1 equals to o2
3. negative – o1 is less than o1
Calling methodCollections.sort(List)
Here objects will be sorted on the basis of CompareTo method
Collections.sort(List, Comparator)
Here objects will be sorted on the basis of Compare method in Comparator
PackageJava.lang.Comparable

 

Java.util.Comparator

Java code:
For Comparable: We will create class country having attribute id and name.This class will implement Comparable interface and implement CompareTo method to sort collection of country object by id.

1. Country.java

package org.arpit.javapostsforlearning;
//If this.cuntryId < country.countryId:then compare method will return -1
//If this.countryId > country.countryId:then compare method will return 1
//If this.countryId==country.countryId:then compare method will return 0
public class Country implements Comparable{
    int countryId;
    String countryName;

    public Country(int countryId, String countryName) {
        super();
        this.countryId = countryId;
        this.countryName = countryName;
    }

    @Override
    public int compareTo(Object arg0) {
        Country country=(Country) arg0;
        return (this.countryId < country.countryId ) ? -1: (this.countryId > country.countryId ) ? 1:0 ;
    }

    public int getCountryId() {
        return countryId;
    }

    public void setCountryId(int countryId) {
        this.countryId = countryId;
    }

    public String getCountryName() {
        return countryName;
    }

    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }

}

2.ComparatorMain.java

package org.arpit.javapostsforlearning;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparatorMain {

	/**
	 * @author Arpit Mandliya
	 */
	public static void main(String[] args) {
		 Country indiaCountry=new Country(1, 'India');
		 Country chinaCountry=new Country(4, 'China');
		 Country nepalCountry=new Country(3, 'Nepal');
		 Country bhutanCountry=new Country(2, 'Bhutan');

	        List<Country> listOfCountries = new ArrayList<Country>();
	        listOfCountries.add(indiaCountry);
	        listOfCountries.add(chinaCountry);
	        listOfCountries.add(nepalCountry);
	        listOfCountries.add(bhutanCountry);

	        System.out.println('Before Sort  : ');
	        for (int i = 0; i < listOfCountries.size(); i++) {
				Country country=(Country) listOfCountries.get(i);
				System.out.println('Country Id: '+country.getCountryId()+'||'+'Country name: '+country.getCountryName());
			}
	        Collections.sort(listOfCountries);

	        System.out.println('After Sort  : ');
	        for (int i = 0; i < listOfCountries.size(); i++) {
				Country country=(Country) listOfCountries.get(i);
				System.out.println('Country Id: '+country.getCountryId()+'|| '+'Country name: '+country.getCountryName());
			}
	}

}

Output:

Before Sort  : 
Country Id: 1||Country name: India
Country Id: 4||Country name: China
Country Id: 3||Country name: Nepal
Country Id: 2||Country name: Bhutan
After Sort  : 
Country Id: 1|| Country name: India
Country Id: 2|| Country name: Bhutan
Country Id: 3|| Country name: Nepal
Country Id: 4|| Country name: China

For Comparator: We will create class country having attribute id and name and will create another class CountrySortByIdComparator which will implement Comparator interface and implement compare method to sort collection of country object by id and we will also see how to use anonymous comparator.

1.Country.java

package org.arpit.javapostsforlearning;

public class Country{
    int countryId;
    String countryName;

    public Country(int countryId, String countryName) {
        super();
        this.countryId = countryId;
        this.countryName = countryName;
    }

    public int getCountryId() {
        return countryId;
    }

    public void setCountryId(int countryId) {
        this.countryId = countryId;
    }

    public String getCountryName() {
        return countryName;
    }

    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }

}

2.CountrySortbyIdComparator.java

package org.arpit.javapostsforlearning;

import java.util.Comparator;
//If country1.getCountryId()<country2.getCountryId():then compare method will return -1
//If country1.getCountryId()>country2.getCountryId():then compare method will return 1
//If country1.getCountryId()==country2.getCountryId():then compare method will return 0
 public class CountrySortByIdComparator implements Comparator<Country>{

    @Override
    public int compare(Country country1, Country country2) {

        return (country1.getCountryId() < country2.getCountryId() ) ? -1: (country1.getCountryId() > country2.getCountryId() ) ? 1:0 ;
    }

}

3.ComparatorMain.java

package org.arpit.javapostsforlearning;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparatorMain {

	/**
	 * @author Arpit Mandliya
	 */
	public static void main(String[] args) {
		 Country indiaCountry=new Country(1, 'India');
		 Country chinaCountry=new Country(4, 'China');
		 Country nepalCountry=new Country(3, 'Nepal');
		 Country bhutanCountry=new Country(2, 'Bhutan');

	        List<Country> listOfCountries = new ArrayList<Country>();
	        listOfCountries.add(indiaCountry);
	        listOfCountries.add(chinaCountry);
	        listOfCountries.add(nepalCountry);
	        listOfCountries.add(bhutanCountry);

	        System.out.println('Before Sort by id : ');
	        for (int i = 0; i < listOfCountries.size(); i++) {
				Country country=(Country) listOfCountries.get(i);
				System.out.println('Country Id: '+country.getCountryId()+'||'+'Country name: '+country.getCountryName());
			}
	        Collections.sort(listOfCountries,new CountrySortByIdComparator());

	        System.out.println('After Sort by id: ');
	        for (int i = 0; i < listOfCountries.size(); i++) {
				Country country=(Country) listOfCountries.get(i);
				System.out.println('Country Id: '+country.getCountryId()+'|| '+'Country name: '+country.getCountryName());
			}

	        //Sort by countryName
	        Collections.sort(listOfCountries,new Comparator<Country>() {

				@Override
				public int compare(Country o1, Country o2) {
					return o1.getCountryName().compareTo(o2.getCountryName());
				}
			});

			System.out.println('After Sort by name: ');
	        for (int i = 0; i < listOfCountries.size(); i++) {
				Country country=(Country) listOfCountries.get(i);
				System.out.println('Country Id: '+country.getCountryId()+'|| '+'Country name: '+country.getCountryName());
			}
	}

}

Output:

Before Sort by id : 
Country Id: 1||Country name: India
Country Id: 4||Country name: China
Country Id: 3||Country name: Nepal
Country Id: 2||Country name: Bhutan
After Sort by id: 
Country Id: 1|| Country name: India
Country Id: 2|| Country name: Bhutan
Country Id: 3|| Country name: Nepal
Country Id: 4|| Country name: China
After Sort by name: 
Country Id: 2|| Country name: Bhutan
Country Id: 4|| Country name: China
Country Id: 1|| Country name: India
Country Id: 3|| Country name: Nepal

 

Reference: Difference between Comparator and Comparable in Java from our JCG partner Arpit Mandliya at the Java frameworks and design patterns for beginners blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....

 

35 comments

  1. Hi Arpit,

    I have a doubt here. even in case of comparable, we can sort the object based on its attributes…like countryId in this case. Does this mean that the main difference is that we can only choose to sort using one attribute in case of comparable, however in case of comparator we can provide various implementations of compare method??

    • Yes, but in different classes. like below.

      ///Sort by ID
      public class CountrySortByIdComparator implements Comparator{

      public int compare(Country country1, Country country2) {
      // your logic
      }

      //Sort By Name
      public class CountrySortByNameComparator implements Comparator{

      public int compare(Country country1, Country country2) {
      // your logic
      }

      //Sort By Designation
      public class CountrySortByDesignationComparator implements Comparator{

      public int compare(Country country1, Country country2) {
      // your logic
      }

      ///// Some where in other class’s Main

      Collections.sort(listOfCountries,new CountrySortByIdComparator());

      Collections.sort(listOfCountries,new CountrySortByNameComparator());

      Collections.sort(listOfCountries,new CountrySortByDesignationComparator());

      • hi,

        As you are saying that you need different class to sort by different attributes. Can I not sort the list on multiple attributes in the same class?

        Thanks
        Sharif

        • Well, NO. This is because one class can have only a single implementation of the Comparator interface. You can’t overload the “compare(obj1,obj2)” method in a given class because the function signature of the compare method cannot be altered otherwise it won’t be invoked at all!
          So for every implementation you need to have a different class that defines the compare method in the desired way.

          Hope this clears your query!

          • Two countries can not same name so in this case, yes, it will be sorted by name only. Lets have a new class Employee. Two Employees can have same name. Please Try with that . You will see, if two employees have same name then they will be sorted by their IDs.

          • It still gives first priority to Names. Mate, you fail to understand that your code sorts by name and goes for the ID ONLY IF the names are same. Refer to the country example. Your code would output the following:-

            2 Bhutan
            4 China
            1 India
            3 Nepal

            This is sorting by name. The ID sort would render the following:-

            1 India
            2 Bhutan
            3 Nepal
            4 China

            So for implementing the ID sort you will be required to have a different class. Hope this clears your confusion.

            Cheers!

          • Hello Farhan,
            I never said we can achieve full sorting based on two different parameters together. Neither my code will do that. It will sort based on ID when the Names are same. Saw your FB profile noticed you are still in college. So I think you never attended any job interview. Its a very good interview question that how to sort a collection of a Class based on two parameter i.e Name or ID. Employee class is very common example for this. Two Employee can have same name but not ID.
            Replying in this thread because not seeing “reply” button after your latest answer.

            Jai

        • As you are saying that you need different class to sort by different attributes? No. It depends on requirement.
          Can I not sort the list on multiple attributes in the same class? Yes.

          How?

          Eg. Lets take Country class from above and make one comparator of it.

          //This Comparator will the Country Collection based on Name and Id both
          public class CountrySortByNameNId implements Comparator{

          public int compare(Country c1, Country c2) {
          int i = c1.getCountryName().compareTo(c2.getCountryName());

          if(i==0)
          i = c1.getCountryId() – c2.getCountryId();

          return i;
          }

          • Jai, you seem to have not understood the concept of sorting by Name and sorting by ID. The two are independent of each other. Check your code for a case where the each country has a different name and a different ID. You will end up sorting them on the basis of their names and not IDs. What you have written is a special case which sorts by ID only if the country names are same, otherwise the sorting implementation relies on the name aspect only. It does not pay heed to the ID at all if all the countries have a unique name. So, ultimately you sort them in the order of their names and not IDs.

            Let’s take the example illustrated in this section. The output of your code will be as follows.

            2 Bhutan
            4 China
            1 India
            3 Nepal

            Your code has sorted the elements based on their names and not IDs. Ergo, you need a DIFFERENT CLASS to implement the ID-based sorting method.

            PS:- In the real world, two countries would never have the same name, so the latter portion of your code which checks for ID, after the names are found to be equal, would never execute.

          • Jai, you seem to have not understood the notion of sorting by name and sorting by ID. The two are indeed separate implementations of the Comparator interface and are independent of each other. Check your code for a case wherein all the countries have different names with unique IDs. You will gradually end up sorting them in the order of their names and not IDs. What you have specified is NOT sorting the country objects by IDs, perhaps it is sorting them by name and if and only if the names of two countries are same(which is practically impossible), it goes for the ID comparison.

            Let’s take the example illustrated as the case. Your code would output the following:-

            2 Bhutan
            4 China
            1 India
            3 Nepal

            So you see, the sorting has been done in order of the names and not IDs. Ergo, you need a DIFFERENT CLASS to implement the ID-based sorting methodology.

            PS:- In the real world, no two countries would ever have the same name, so the latter portion of your code that checks for IDs, after the names are found to be identical, would practically be never executed.

      • Jai,
        That’s exactly what I have been saying since the last so many comments – We can’t achieve full sorting based on two different parameters together. You finally got the point. Your code is plain and simple and does not do any massive task. I completely understand your code’s logic. It’s quite trivial.

        My being in college and not having appeared for any interview is immaterial of what I perceive of this question. I know quite a lot of people who have appeared for several interviews and yet are unable to produce a simple trivial code that many college going students can easily come up with. Well, to add to your “highly-interview-experienced” coding skills, I suggest you must try these:-

        https://blog.svpino.com/2015/05/07/five-programming-problems-every-software-engineer-should-be-able-to-solve-in-less-than-1-hour?utm_source=facebook&utm_medium=social&utm_content=Oktopost-facebook-profile&utm_campaign=Oktopost-2015-05+General+Campaign

        Focus on the last pair.
        Cheers!

  2. Comparator is easy to understand but sometimes a bit confusing because of the difficult to grab documentation from oracle or earlier Sun. It is one of the most important things you need to know while working with java.

    Try reading it here http://javahash.com/java-comparator-and-comparable-demystified/

  3. very good explaination

  4. hey dude ,
    Please remove the line numbers from the above code as those line no are also getting copied while copying the code

  5. Very good explanation, will be very beneficial for java learners.

  6. Very good explanation …..Thanks to all……

  7. please change the name of the class to ComparableMain instead of comparatorMain in the first sort program. That created a lot of disturbance for me to understand

  8. very good and detailed article

  9. Very good explanation, but I have a question. As everyone keep saying that compareTo method returns positive, negative etc values. I am just curious about who needs those values , I mean we simply call a sort method and the class whose objects we wanna sort implements comparable interface and we simply say in compareTo() method if one objects attrib is less or whatever than other then return something, ok if i have 10 objects in my list and in compareTo() we are saying the same thing as said above, then are first two objects in list first compared or something else happens .

    • I think if there are more objects to compare in the list, Collections.sort(list) would call compareTo method implemented in the (comparable) class, 2 objects at a time and sort it accordingly.

      For example: If ID is in this order on the list when added: 2,1,4,3.

      2 and 1 compared first, the result would be 1,2 (if the implementation of compareTo is natural ordering and it would return positive number)
      2 and 4 compared second, the result would be 2,4 (compareTo would return negative number)
      4 and 3 compared third, the result would be 3,4 (compareTo would return negative number)

      End result: 1,2,3,4

  10. Hi all,

    I have written sample program which implements comparable where you need not to explicitly put comparison logic inside compareTo method as below.

    return (this.countryId country.countryId ) ? 1:0 ;

    Please see my program for the difference,

    ##################################################################################
    package com.cisco.srini;

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;

    class CompareProgram implements Comparable{

    private final int petId;
    private final String petType;

    public CompareProgram(int petId, String petType) {

    this.petId = petId;
    this.petType = petType;
    }

    public int compareTo(Object o) {

    CompareProgram cmpObj = (CompareProgram)o;

    SOP(“Current PetType:”+this.petType);
    SOP(“Object to be compared:”+cmpObj.petType);

    int result = this.petType.compareTo(cmpObj.petType);
    SOP(“Compare value:”+result);

    return result;
    }

    public String toString(){
    return (petId+petType);
    }

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    List list = new ArrayList();
    list.add(new CompareProgram(1, “Parrot”));
    list.add(new CompareProgram(2, “Dog”));
    list.add(new CompareProgram(3, “Cat”));
    list.add(new CompareProgram(4, “Rabbit1″));
    list.add (new CompareProgram(5,”Rabbit1″));

    // Internally it dumps the list into an array, sorts the array and then resets the index position of list copied from array.
    Collections.sort(list);

    for(Iterator iter = list.iterator();iter.hasNext();){
    CompareProgram element = (CompareProgram) iter.next();
    System.out.println(“Sorted element”+element);
    }

    }

    }

    ###################################################################################

  11. Hi,

    Thanks for the tutorial.

    1) If you make use of generics then please do not cast to the generic type !
    Country country=(Country) listOfCountries.get(i);
    must become
    Country country=listOfCountries.get(i);
    It is not necessary anymore as you will use a foreach loop.

    2) Do you know the foreach looping ?
    for (int i = 0; i < listOfCountries.size(); i++) {
    Country country = (Country) listOfCountries.get(i);
    System.out.println("Country Id: " + country.getCountryId() + "||"
    + "Country name: " + country.getCountryName());
    }
    must become
    for (Country country : listOfCountries) {
    System.out.println("Country Id: " + country.getCountryId() + "|| "
    + "Country name: " + country.getCountryName());
    }

    Kind regards,

    -Rudy-

  12. Sorting logic is in separate class. Hence we can write different sorting based on different attributes of objects to be sorted.Is this mean applying differant sorting methods like bubble,quick etc sorts ?

  13. This is very clear. Nice presentation.

  14. And want to add one point with respect to use case. When we have control in Class to do implement we can use directly comparable. Otherwise, if it is a third party class, then we need to use Comparator for our own purpose.

  15. Hi Arpit,

    Blog is very nice, it helps me too much for the differences in these two. I think, just there is one minor print mistake while comparing in Comparator section i.e. “3. negative – o1 is less than o1″ in third point

    Thanks..!!!

  16. Thanks for you post.Very well description.

  17. Thanks for the post. so helpful for understanding.

  18. Hello author,

    As I found that you need different class to sort by different attributes. Can I not sort the list on multiple attributes in the same class?

    Thanks
    Sharif

Leave a Reply

Your email address will not be published. Required fields are marked *

*


8 + six =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Want to take your Java Skills to the next level?
Grab our programming books for FREE!
  • Save time by leveraging our field-tested solutions to common problems.
  • The books cover a wide range of topics, from JPA and JUnit, to JMeter and Android.
  • Each book comes as a standalone guide (with source code provided), so that you use it as reference.
Last Step ...

Where should we send the free eBooks?

Good Work!
To download the books, please verify your email address by following the instructions found on the email we just sent you.