Main Tutorials

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

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
113 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Arsen Khachatryan
6 years ago

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

andrey
6 years ago

very good!

Milind Durugkar
9 years ago

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

Nhaan
3 years ago

Thanks a lot, hoho

srikanth
5 years ago

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

Neha Jain
5 years ago

Very well explained

ankit
6 years ago

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.

elvis
6 years ago

good article

Budulla Akhlaaq
6 years ago

how do u apply this to a textfile?

Hidayath
6 years ago

Nice!!!
Please update the link to ‘Comparable Docum…’ (http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Comparable.html)

Luki R Daniel
6 years ago

Beautiful example! Thanks

kammiti krishna
8 years ago

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

ankit
6 years ago

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

akash rathod
8 years ago

how can we sort this Object Arraylist

ArrayList objt = new ArrayList();

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

Leo Messi
8 years ago

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

Rohan Sethi
8 years ago

The doc reference link is broken.

infoj
8 years ago

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

infoj
8 years ago

Actually limitation with comparable has to do with natural ordering which you have already defined for your class … If you want your collection to be sorted in any other way, than the natural ordering you have defined, then you have to write a comparator.

See my post too – http://netjs.blogspot.in/2015/08/how-to-sort-arraylist-of-custom-objects-java.html

Raihan Uddin Maksud
8 years ago

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

manas ranjan dhal
8 years ago

The best ever site …..for self learner

Deo Priya
8 years ago

can comparator instances be public ?

AnonyMouse
8 years ago

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());
}

Sridhar.Goranti
9 years ago

Thank you mkyong. It was very useful 🙂

Mahadev
9 years ago

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

kuku
9 years ago

thank you for sharing this tutorial , it is great 🙂

Andrea
9 years ago

Thank you very much, your guide was really helpful

Vivek Pal
9 years ago

To the point explanation
Thanks

Chris
9 years ago

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.

Ramtin
9 years ago

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

JJ
9 years ago

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

nisha
9 years ago

why super() is used in Fruit class(no.3) ?