Java object sorting example (Comparable and Comparator)

In this tutorial, it shows the use of java.lang.Comparable and java.util.Comparator to sort a Java object based on its property value.

1. Sort an Array

To sort an Array, use the Arrays.sort().


	String[] fruits = new String[] {"Pineapple","Apple", "Orange", "Banana"}; 
		
	Arrays.sort(fruits);
		
	int i=0;
	for(String temp: fruits){
		System.out.println("fruits " + ++i + " : " + temp);
	}

Output


fruits 1 : Apple
fruits 2 : Banana
fruits 3 : Orange
fruits 4 : Pineapple

2. Sort an ArrayList

To sort an ArrayList, use the Collections.sort().


	List<String> fruits = new ArrayList<String>();
		 
	fruits.add("Pineapple");
	fruits.add("Apple");
	fruits.add("Orange");
	fruits.add("Banana");
	
	Collections.sort(fruits);
		
	int i=0;
	for(String temp: fruits){
		System.out.println("fruits " + ++i + " : " + temp);
	}

Output


fruits 1 : Apple
fruits 2 : Banana
fruits 3 : Orange
fruits 4 : Pineapple

3. Sort an Object with Comparable

How about a Java Object? Let create a Fruit class:


public class Fruit{
	
	private String fruitName;
	private String fruitDesc;
	private int quantity;
	
	public Fruit(String fruitName, String fruitDesc, int quantity) {
		super();
		this.fruitName = fruitName;
		this.fruitDesc = fruitDesc;
		this.quantity = quantity;
	}
	
	public String getFruitName() {
		return fruitName;
	}
	public void setFruitName(String fruitName) {
		this.fruitName = fruitName;
	}
	public String getFruitDesc() {
		return fruitDesc;
	}
	public void setFruitDesc(String fruitDesc) {
		this.fruitDesc = fruitDesc;
	}
	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}
}

To sort it, you may think of Arrays.sort() again, see below example :


package com.mkyong.common.action;

import java.util.Arrays;

public class SortFruitObject{
	
	public static void main(String args[]){

		Fruit[] fruits = new Fruit[4];
		
		Fruit pineappale = new Fruit("Pineapple", "Pineapple description",70); 
		Fruit apple = new Fruit("Apple", "Apple description",100); 
		Fruit orange = new Fruit("Orange", "Orange description",80); 
		Fruit banana = new Fruit("Banana", "Banana description",90); 
		
		fruits[0]=pineappale;
		fruits[1]=apple;
		fruits[2]=orange;
		fruits[3]=banana;
		
		Arrays.sort(fruits);

		int i=0;
		for(Fruit temp: fruits){
		   System.out.println("fruits " + ++i + " : " + temp.getFruitName() + 
			", Quantity : " + temp.getQuantity());
		}
		
	}	
}

Nice try, but, what you expect the Arrays.sort() will do? You didn’t even mention what to sort in the Fruit class. So, it will hits the following error :


Exception in thread "main" java.lang.ClassCastException: 
com.mkyong.common.Fruit cannot be cast to java.lang.Comparable
	at java.util.Arrays.mergeSort(Unknown Source)
	at java.util.Arrays.sort(Unknown Source)

To sort an Object by its property, you have to make the Object implement the Comparable interface and override the compareTo() method. Lets see the new Fruit class again.


public class Fruit implements Comparable<Fruit>{
	
	private String fruitName;
	private String fruitDesc;
	private int quantity;
	
	public Fruit(String fruitName, String fruitDesc, int quantity) {
		super();
		this.fruitName = fruitName;
		this.fruitDesc = fruitDesc;
		this.quantity = quantity;
	}
	
	public String getFruitName() {
		return fruitName;
	}
	public void setFruitName(String fruitName) {
		this.fruitName = fruitName;
	}
	public String getFruitDesc() {
		return fruitDesc;
	}
	public void setFruitDesc(String fruitDesc) {
		this.fruitDesc = fruitDesc;
	}
	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}

	public int compareTo(Fruit compareFruit) {
	
		int compareQuantity = ((Fruit) compareFruit).getQuantity(); 
		
		//ascending order
		return this.quantity - compareQuantity;
		
		//descending order
		//return compareQuantity - this.quantity;
		
	}	
}

The new Fruit class implemented the Comparable interface, and overrided the compareTo() method to compare its quantity property in ascending order.

The compareTo() method is hard to explain, in integer sorting, just remember

  1. this.quantity – compareQuantity is ascending order.
  2. compareQuantity – this.quantity is descending order.

To understand more about compareTo() method, read this Comparable documentation.

Run it again, now the Fruits array is sort by its quantity in ascending order.


fruits 1 : Pineapple, Quantity : 70
fruits 2 : Orange, Quantity : 80
fruits 3 : Banana, Quantity : 90
fruits 4 : Apple, Quantity : 100

4. Sort an Object with Comparator

How about sorting with Fruit’s “fruitName” or “Quantity”? The Comparable interface is only allow to sort a single property. To sort with multiple properties, you need Comparator. See the new updated Fruit class again :


import java.util.Comparator;

public class Fruit implements Comparable<Fruit>{
	
	private String fruitName;
	private String fruitDesc;
	private int quantity;
	
	public Fruit(String fruitName, String fruitDesc, int quantity) {
		super();
		this.fruitName = fruitName;
		this.fruitDesc = fruitDesc;
		this.quantity = quantity;
	}
	
	public String getFruitName() {
		return fruitName;
	}
	public void setFruitName(String fruitName) {
		this.fruitName = fruitName;
	}
	public String getFruitDesc() {
		return fruitDesc;
	}
	public void setFruitDesc(String fruitDesc) {
		this.fruitDesc = fruitDesc;
	}
	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}

	public int compareTo(Fruit compareFruit) {
	
		int compareQuantity = ((Fruit) compareFruit).getQuantity(); 
		
		//ascending order
		return this.quantity - compareQuantity;
		
		//descending order
		//return compareQuantity - this.quantity;
		
	}
	
	public static Comparator<Fruit> FruitNameComparator 
                          = new Comparator<Fruit>() {

	    public int compare(Fruit fruit1, Fruit fruit2) {
	    	
	      String fruitName1 = fruit1.getFruitName().toUpperCase();
	      String fruitName2 = fruit2.getFruitName().toUpperCase();
	      
	      //ascending order
	      return fruitName1.compareTo(fruitName2);
	      
	      //descending order
	      //return fruitName2.compareTo(fruitName1);
	    }

	};
}

The Fruit class contains a static FruitNameComparator method to compare the “fruitName”. Now the Fruit object is able to sort with either “quantity” or “fruitName” property. Run it again.

1. Sort Fruit array based on its “fruitName” property in ascending order.


Arrays.sort(fruits, Fruit.FruitNameComparator);

Output


fruits 1 : Apple, Quantity : 100
fruits 2 : Banana, Quantity : 90
fruits 3 : Orange, Quantity : 80
fruits 4 : Pineapple, Quantity : 70

2. Sort Fruit array based on its “quantity” property in ascending order.


Arrays.sort(fruits)

Output


fruits 1 : Pineapple, Quantity : 70
fruits 2 : Orange, Quantity : 80
fruits 3 : Banana, Quantity : 90
fruits 4 : Apple, Quantity : 100
The java.lang.Comparable and java.util.Comparator are powerful but take time to understand and make use of it, may be it’s due to the lacking of detail example.

My thoughts…

In future, Arrays class should provides more generic and handy method – Arrays.sort(Object, String, flag).

To sort a object array by its “fruitName” in ascending order.


Arrays.sort(fruits, fruitName, Arrays.ASCENDING);

To sort a object array by its “quantity” in ascending order.


Arrays.sort(fruits, quantity, Arrays.DESCENDING);

Reference

  1. Comparable documentation
  2. Comparator documentation

113 comments on “Java object sorting example (Comparable and Comparator)

  1. please help on developing the spring boot application for a fruit store market. requirement is to develop an inventory that manages the stock of fruits and aging of the fruits , managing the damaged fruits etc..

    Reply
  2. Good example,
    How you will compare the list which has two string properties. For example:

    List dataList = new ArrayList();
    Data d = new Data();
    d.setCode(“CH”);
    d.setDisplayValue(“C value”);
    dataList.add(d);
    d = new Data();
    d.setCode(“AH”);
    d.setDisplayValue(“A value”);
    dataList.add(d);
    d = new Data();
    d.setCode(“B0”);
    d.setDisplayValue(“B value”);
    dataList.add(d);
    d = new Data();
    d.setCode(“B1”);
    d.setDisplayValue(“B1 value”);
    dataList.add(d);
    d = new Data();
    d.setCode(“DH”);
    d.setDisplayValue(“D value”);
    dataList.add(d);

    How can you sort by display value (DisplayValue)?
    Thanks in advance

    Reply
  3. If ur class is Employee and the three parameter in this class like name, name, salary
    1. If you want to sort by name then you can use first Compairable interface like:

    class Employee implements Compairable{
    public Employee (String name, String age, int salary) {
    super();
    this.name= name;
    this.age= age;
    this.salary= salary;
    }
    String name;
    int age;
    double salary;

    public int compareTo(Employee employee) {
    return this.name.equalsIgnoreCase(employee.getname());
    }
    }
    Employee employee = new Employee (“a”,25,9000);
    Note: No need to pass this in sort method.

    2.If also you have requirement to sort by age then you can create Agecomparator class and you can use this age comparator like:
    Agecomparator implements Comparator() {

    public int compare(Employee emp1, Employee emp2) {
    if(emp1>emp2){
    return 1;
    }else if(emp1<emp2){
    return -1;
    }else ifemp1==emp2){
    return 0;
    }
    return fruitName1.compareTo(fruitName2);
    }
    }

    Collections.sort(list, Agecomparator).

    Note : if you need sortting according multiple bases like age, salary etc then you can use Comparator.

    Reply
  4. In future, Arrays class should provides more generic and handy method – Arrays.sort(Object, String, flag).
    This is very bad design

    Reply
  5. Hai everyone,

    Can I pass set implementation class object as parameter of sort() method like
    Collections.sort(Set object ):
    Need justify answer with proof…

    Reply
  6. ((Fruit) compareFruit).getQuantity() whats going here iam not understood

    Reply
    1. its type casting but no need to type cast compareFruit in Fruit because its already Fruit object.

      Reply
  7. how can we sort this Object Arraylist

    ArrayList objt = new ArrayList();

    objt.add(4);
    objt.add(5);
    objt.add(6);
    objt.add(1);

    Reply
  8. Hi,
    Can you tell me what is this ? Why it is used ?
    And How this works ?
    //ascending order
    return fruitName1.compareTo(fruitName2);

    //descending order
    //return fruitName2.compareTo(fruitName1);

    Reply
  9. Since Comparator is a functional interface so we can use lambda expression to provide implementation of its abstract method. That will reduce the custom comparator implementation to a single line. Don’t forget to import the comparator interface though.

    As example if I have list of coties cityList then it can be sorted using lambda expression this way

    Collections.sort(cityList, (String a, String b)-> b.compareTo(a));

    Read more here – http://netjs.blogspot.in/2015/08/how-to-sort-arraylist-in-java.html

    Reply
  10. this is the best web of blog what ever for java tutorial

    Reply
  11. The best ever site …..for self learner

    Reply
  12. This is off-topic but why do you use an int and a for-each loop in most of your examples?
    Like the following:

    int i=0;
    for(String temp: fruits) {
    System.out.println(“fruits ” + ++i + ” : ” + temp);
    }

    Why not just use a regular old for loop?

    for(int i=0; i<fruits.length; i++) {
    System.out.println("fruits " + i + " : " + fruits[i].toString());
    }

    Reply
  13. would like to know…internally what sorting technique is used when we use comparable or comparator to compare objects in collection

    Reply
  14. thank you for sharing this tutorial , it is great 🙂

    Reply
  15. Thank so very much! I used this to great value in a project where I needed to sort Edges of a graph by their numeric label, and later on I needed to topologically sort the whole graph, so I defined a comparator that sorted by postvisit time. Works like a charm.

    Reply
  16. Shouldn’t it be: public int compareTo(Object fruit){…} in order it inherits the compareTo-method?

    Reply
  17. This class implements the Comparator interface. You should consider whether or not it should also implement the Serializable interface. If a comparator is used to construct an ordered collection such as a TreeMap, then the TreeMap will be serializable only if the comparator is also serializable. As most comparators have little or no state, making them serializable is generally easy and good defensive programming.
    findbugs SE_COMPARATOR_SHOULD_BE_SERIALIZABLE

    Reply
  18. Where to write main method in this program and how to call

    Arrays.sort(fruits, fruitName, Arrays.ASCENDING); I tried but it is giving compile time error

    Reply
  19. CompareTo method not required in Fruit Class. As you are using String.CompareTo(String) not object.ComparTo(Object).

    Reply
  20. made many stops here for reference. i love this write up. when i forget, i will just drop by here for reference. great writeup.

    Reply
  21. To compare with Strings, we can use the compareToIgnoreCase() method which returns a positive, negative or a 0 depending upon whether the first string has a greater, lesser or the same character as that of the second string. It is done through lexicographical comparison which means that the compareToIgnoreCase() method compares character by character starting from the left and as soon as it reaches a character which is different, it returns the corresponding values as stated above.

    Here’s the code snippet of the overridden compareTo() method,
    public int compareTo(Object obj)
    {
    Fruit fruit=(Fruit)obj;
    return this.fruitName.compareToIgnoreCase(fruit.fruitName);
    }

    Reply
  22. Thank you for clarifying the reason to use comparable and comparator. It is better to know why they are needed before the details of how to write the code. Thanks a lot!

    Reply
  23. Thank you so much. I understand very quickly.

    Reply
  24. When I want to sort an array of objects the object should implement the Comparable! If I want to compare using the Comparator should my class implements Comparable again?

    Reply
  25. I seriously appreciate your thought on Arrays.sort(Object, String, flag). . it looks better this way

    Reply
  26. Thanks @mkyong.

    One comment : The statement, “The Fruit class contains a static FruitNameComparator method to compare the “fruitName”” is wrong. FruitNameComparator is a static instance variable of type Comparator in Fruit class. Also, I think it’s not mandatory for it to exist as a static member under Fruit, as this could be an equivalent:

    class FruitComparator implements Comparator {
    public int compare(Fruit f1, Fruit f2) {
    return (f1.getFruitName().toUpperCase()).compareTo((f2.getFruitName().toUpperCase()));
    }
    }

    Arrays.sort(fruits, new FruitNameComparator()); would be the call in the main method.

    Reply
    1. You are right Shishir, I also noticed the wrong sentence, and I totally agree with your alternative implementation proposal.

      Reply
      1. thats why mk said ClassCastException occurence

        people you look on clear way……..

        Reply
    2. you are right. Additionally, If I am use sorting only at one place, I prefer giving the comparator implementation as an anonymous class.

      Arrays.sort(fruits, new Comparator(){public int compare(Fruit f1, Fruit f2) {…}});

      Reply
  27. if i don’ t know how many objects, i think would use List replacement for array[]

    have the differences between use list and arrary[] ???

    Reply
  28. Awesome..!!! a simple and clear Explanation…just want to add one doesn’t need to implement Comparable Interface if they only want to use Comparator…

    thanks Man..:))

    Reply
  29. I think it’s not this

    Arrays.sort(fruits, Fruit.FruitNameComparator);

    but this

    Collections.sort(fruits, Fruit.FruitNameComparator);

    Reply
  30. your implementation of comparator is very advanced so I didn’t understand it, however comparable was ok. could you please simplify it for me a total beginner to understand? If you don’t mind send your simplified version of comparator to [email protected]

    Thanks for help.

    Reply
  31. I am just curious about the static fields used in the anonymous class instantiation: Should we put those static fields in a different class?
    Or should they remain in the bean?

    Thanks!

    Reply
  32. your Arrays.sort(fruits, fruitName, Arrays.ASCENDING); doesn’t make any sense, unless it is “fruitName” which is very unJava-like. Java 8 or 9 should provide lambdas, though to lessen the need for tons of ridiculously short classes such as Comparators.

    Reply
  33. I think your code (for comparator) is somewhat wrong. The class whose objects are to be sorted using compare() must implement Comparator, but u’ve only implemented Comparable.

    Reply
  34. >In future, Arrays class should provides more generic and handy method ? Arrays.sort(Object, String, flag).
    OMG, desc is a mirrored asc, sort it asc, and mirror.

    Reply
  35. Thank you man.
    It wored perfectly for me even for the android.
    Thank you sooooooooooo much

    you deserve better!!!!

    Reply
  36. mkyong,

    the problem with your code (sorting by value) yes it works on one platform but not on all. On eclipse I see error marks almost on every line of code but it still compiles. When I take it outside of eclipse it does not compile. The primary reason being parameter not specified.

    Reply
  37. i was looking for a lightweight and easy to understand implementation of comparable and comparator. Thanks a tonn for this.

    Reply
  38. what is the need of hascode&equals override..

    the simple examle.

    Reply
  39. Sir,can you explaine me pseudocode for CompareTo() and Compare().

    Reply
  40. That’s a nice example.
    What if i want to sort my list in a specific order:
    For example : The fruits should always be sorted as : banana, apple, pineapple, orange.
    How compareTo() or comparable will work in such scenario ?

    Reply
  41. Thanks a lot for this great post!.
    I have a question. can we sort Object based on two attributes like name and ID at a single time? According to above example at a time we can sort eihter by id or name.
    Thanks

    Reply
  42. Hi, in this compareTo method

    public int compareTo(Fruit compareFruit)

    you are passing an object of type Fruit.

    And inside the method,

    int compareQuantity = ((Fruit) compareFruit).getQuantity();

    You are again casting the Fruit object to a Fruit data type…

    Is it really necessary? Just compareFruit.getQuantity() should do the job i guess.

    Sorry if i am wrong.

    Reply
  43. Yong,

    I am following your posts since a month now.
    I became a follower of you after seeing few posts.

    I really appreciate your help to all Java developers. Each of these examples are very simple to understand and can be extended from then.

    Raju Cherukuri

    Reply
  44. “The Comparable interface is only allow to sort a single property.”

    Wait, what? Properties can be compared one by one. If one of them, when compared, returns 0, we can proceed comparison.

    Reply
  45. This example really helped me as these two comparable and comparator are very confusing.
    But I have the following points:

    1) Comparable can be used for int value value.
    2) How can we use multiple fields sorting using comparator like Sorting on Country, State
    and City order?

    Can you please mail me the solution?

    Reply
    1. Hi Santosh, I also had a similar scenario as yours with the 1st question. It actually works with Object types. Therefore, you will not be able to do Collection.sort() instead you can use Arrays.sort(). However if you still want to use Collection.sort() with primitive types such as int,long & etc.. you can cast them to their wrapper classes for example Integer, Long and continue to use Collection.sort(). Thanks! 🙂

      Reply
  46. Very nice…
    Make me understand easy..
    Thank you…..

    Reply
  47. Nice tutorial! Taught me what I needed to know to quickly implement a sort in my program.

    One thing that might be useful for future readers is an explanation of this part of the code:

    public int compareTo(Fruit compareFruit) {
     
    		int compareQuantity = ((Fruit) compareFruit).getQuantity(); 
     
    		//ascending order
    		return this.quantity - compareQuantity;
     
    		//descending order
    		//return compareQuantity - this.quantity;
     
    	}

    It took me a minute to figure out what was going on here, especially since the fields I’m comparing are not integers, and this method requires an integer return type. The main idea, for those of you new to Comparable, is that to sort ascending, return a positive number (I returned +1) if this.quantity > compareQuantity. Return a negative number (-1) if this.quantity < compareQuantity. Return 0 if they are equal. (To sort descending, return -1, +1, and 0, respectively.)

    Reply
  48. My annotation lib for implementing Comparable and Comparator:

     
        public class Person implements Comparable<Person> {         
            private String firstName;  
            private String lastName;         
            private int age;         
            private char gentle;         
    
            @Override         
            @CompaProperties({ @CompaProperty(property = "lastName"),              
                @CompaProperty(property = "age",  order = Order.DSC) })           
            public int compareTo(Person person) {                 
                return Compamatic.doComparasion(this, person);         
            }  
        }
    

    Click the link to see more examples.
    http://code.google.com/p/compamatic/wiki/CompamaticByExamples

    Reply

Leave a Comment

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