In this tutorial, you will learn how to sort an ArrayList of Objects by property using comparable and comparator interface. If you are looking for sorting a simple ArrayList
of String or Integer then you can refer the following tutorials –
We generally use Collections.sort()
method to sort a simple array list. However if the ArrayList is of custom object type then in such case you have two options for sorting- comparable and comparator interfaces.
What’s the need of comparable and comparator?
Before going through the example of sorting an ArrayList using comparable and comparator, let’s see what happens when we try to sort arraylist of Objects without implementing any of these interfaces. Consider the following example – We have a Student class which has properties like Student name, roll no and student age.
public class Student { private String studentname; private int rollno; private int studentage; public Student(int rollno, String studentname, int studentage) { this.rollno = rollno; this.studentname = studentname; this.studentage = studentage; } public String getStudentname() { return studentname; } public void setStudentname(String studentname) { this.studentname = studentname; } public int getRollno() { return rollno; } public void setRollno(int rollno) { this.rollno = rollno; } public int getStudentage() { return studentage; } public void setStudentage(int studentage) { this.studentage = studentage; } }
And I want to have an ArrayList of Student Object, which can be defined like this:
import java.util.*; public class ArrayListSorting { public static void main(String args[]){ ArrayList<Student> arraylist = new ArrayList<Student>(); arraylist.add(new Student(223, "Chaitanya", 26)); arraylist.add(new Student(245, "Rahul", 24)); arraylist.add(new Student(209, "Ajeet", 32)); Collections.sort(arraylist); for(Student str: arraylist){ System.out.println(str); } } }
I tried to call the Collections.sort()
on the List of Objects and boom! I got the the following error message:
Exception in thread "main" java.lang.Error: Unresolved compilation problem: Bound mismatch: The generic method sort(List) of type Collections is not applicable for the arguments (ArrayList). The inferred type Student is not a valid substitute for the bounded parameter > at beginnersbook.com.Details.main(Details.java:11)
Reason: I Just called the sort method on an ArrayList of Objects which actually doesn’t work until unless we use interfaces like Comparable
and Comparator
.
Now you must have understood the importance of these interfaces. Let’s see how to use them to sort an ArrayList of objects.
Sorting of ArrayList<Object> with Comparable
Let’s say we need to sort the ArrayList<Student> based on the student Age property. This is how it can be done – First implement Comparable
interface and then Override the compareTo
method.
package beginnersbook.com; public class Student implements Comparable { private String studentname; private int rollno; private int studentage; public Student(int rollno, String studentname, int studentage) { this.rollno = rollno; this.studentname = studentname; this.studentage = studentage; } ... //getter and setter methods same as the above example ... @Override public int compareTo(Student comparestu) { int compareage=((Student)comparestu).getStudentage(); /* For Ascending order*/ return this.studentage-compareage; /* For Descending order do like this */ //return compareage-this.studentage; } @Override public String toString() { return "[ rollno=" + rollno + ", name=" + studentname + ", age=" + studentage + "]"; } }
Now we can very well call Collections.sort on ArrayList
import java.util.*; public class ArrayListSorting { public static void main(String args[]){ ArrayList<Student> arraylist = new ArrayList<Student>(); arraylist.add(new Student(223, "Chaitanya", 26)); arraylist.add(new Student(245, "Rahul", 24)); arraylist.add(new Student(209, "Ajeet", 32)); Collections.sort(arraylist); for(Student str: arraylist){ System.out.println(str); } } }
Output:
[ rollno=245, name=Rahul, age=24] [ rollno=223, name=Chaitanya, age=26] [ rollno=209, name=Ajeet, age=32]
Comparable did our job why do we need Comparator anymore?
Since Comparable is implemented by the same class whose objects are sorted so it binds you with that sorting logic which is ok in most of the cases but in case you want to have more than way of sorting your class objects you should use comparators. Read more about them here:
Sorting ArrayList<Object> multiple properties with Comparator
We are overriding compare
method of Comparator
for sorting.
package beginnersbook.com; import java.util.Comparator; public class Student { private String studentname; private int rollno; private int studentage; public Student(int rollno, String studentname, int studentage) { this.rollno = rollno; this.studentname = studentname; this.studentage = studentage; } ... //Getter and setter methods same as the above examples ... /*Comparator for sorting the list by Student Name*/ public static Comparator<Student> StuNameComparator = new Comparator<Student>() { public int compare(Student s1, Student s2) { String StudentName1 = s1.getStudentname().toUpperCase(); String StudentName2 = s2.getStudentname().toUpperCase(); //ascending order return StudentName1.compareTo(StudentName2); //descending order //return StudentName2.compareTo(StudentName1); }}; /*Comparator for sorting the list by roll no*/ public static Comparator<Student> StuRollno = new Comparator<Student>() { public int compare(Student s1, Student s2) { int rollno1 = s1.getRollno(); int rollno2 = s2.getRollno(); /*For ascending order*/ return rollno1-rollno2; /*For descending order*/ //rollno2-rollno1; }}; @Override public String toString() { return "[ rollno=" + rollno + ", name=" + studentname + ", age=" + studentage + "]"; } }
ArrayList class:
package beginnersbook.com; import java.util.*; public class Details { public static void main(String args[]){ ArrayList<Student> arraylist = new ArrayList<Student>(); arraylist.add(new Student(101, "Zues", 26)); arraylist.add(new Student(505, "Abey", 24)); arraylist.add(new Student(809, "Vignesh", 32)); /*Sorting based on Student Name*/ System.out.println("Student Name Sorting:"); Collections.sort(arraylist, Student.StuNameComparator); for(Student str: arraylist){ System.out.println(str); } /* Sorting on Rollno property*/ System.out.println("RollNum Sorting:"); Collections.sort(arraylist, Student.StuRollno); for(Student str: arraylist){ System.out.println(str); } } }
Output:
Student Name Sorting: [ rollno=505, name=Abey, age=24] [ rollno=809, name=Vignesh, age=32] [ rollno=101, name=Zues, age=26] RollNum Sorting: [ rollno=101, name=Zues, age=26] [ rollno=505, name=Abey, age=24] [ rollno=809, name=Vignesh, age=32]
Recommended Articles:
Francis says
nice tutorial
Kirjsten says
This was awesome!
Joseph Tran says
Hey sir. Why my netbeans says that student is not an abstract class and doesn’t override the methods from Comparator even i used same codes with yours
Asmaa Hassan says
i had error when override the compareto method “method doesnot override or implement a method from a supertype” when i replace(object o )with (Student comparestu)
Amit says
I am also facing the same error, even after i copy paste this same syntax. There is some problem with the way we are overriding the method.
Joseph MBOGBA says
Dear Joseph & Asmaa,
I have just faced the same issue and I realize that Comparable interface assume Object as parameter by default.
Therefore, we should use (Object comparestu) as parameter when overriding compareTo method. However, we then need to make sure comparestu is of type Student,by casting:(Student)comparestu, to be able to access getStudentage method.
This hassle can be avoided by specifying the parameter of Comparable interface when implemented: Comparable in our case. (Student comparestu)will be compareTo parameter, with no need to cast at this line: int compareage=comparestu.getStudentage();
HarishKumar says
Simply superb examples and great explanation…
Andrey says
In your first example you forgot to specify the type…
implements Comparable
Saby says
yeah and once the type is mentioned, he doesn’t need to typecase inside the compareTo method coz he’s already getting the argument as Student.
Michelle says
GREAT explanation!
I have a question, how do you print out an object with the highest value of one of their properties.
Lets say, I want to print out the name of the student with the highest age from an array list of 100 students. how do you do that?
Dan says
This is great for sorting by one field in a custom object. Can you advise on how to sort by multiple criteria?
for example, sort by age then sort by name then…
Zain says
Thanks a lot for Joseph MBOGBA for the clarification!
Nilesh says
good tutorial
its cleared ma comparable nd comparator concepts
Mehroz Munir says
@Dan and others who want to sort for multiple values like first by age then by name they could use this
suppose you have list of some objects , call these mehtods of sorting in order in which you want to sort the list
Collections.sort(list, new Comparator() {
@Override
public int compare(Campain lhs, Campain rhs) {
Date lhsDate = new Date();
Date rhsDate = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat(“yyyy-MM-dd hh:mm:ss”);
try {
lhsDate = dateFormat.parse(lhs.getDatetime());
rhsDate = dateFormat.parse(rhs.getDatetime());
} catch (ParseException e) {
e.printStackTrace();
}
//return lhsDate.getTime() <= rhsDate.getTime() ? -1 : 1;
// if (rhsDate.getTime() == lhsDate.getTime())
// return 0;
// return rhsDate.getTime() < lhsDate.getTime() ? -1 : 1;
return rhsDate.compareTo(lhsDate);
}
});
then calll this method again for sorting
Rajan Chauhan says
Hi thanks for the awesome description. I want to ask something 1. Is comparable used only for sorting based on an integer property ?? because in other threads it can be used to sort string and other type as well and its working.
2. The code for the comparbles compareTO()method here is taking Student object as parameter, and its not working when i tried, although when passing only base Object type and than casting student from it works well.
public int compareTo(Object obj){
Student st=(Student)obj;
Minh says
Very helpful, awesome thread. Thank you very much.
Rishabh Tripathi says
what if there 2 student with SAME NAME but different Roll no and want to sort according to name and then roll no ?
Gaurav says
still the program ArrayListSorting will give an error :-
Student is not abstract and does not override the abstract method compareTo(Object) in Comparable.
so to remove this error change the line
public int compareTo(Student comparestu) {
from the Comparable program as :-
public int compareTo(Object comparestu) {
this will make program execute. and output will come.
[ rollno=245, name=Rahul, age=24]
[ rollno=223, name=Chaitanya, age=26]
[ rollno=209, name=Ajeet, age=32]
Akaash Trivedi says
Thank you so much.
I was trying to solve same problem since many day finally I did change accordingly your then it got executed.
sunilj says
Thanks for sharing good tutorial.
iCommentr says
You can also sort String type using Comparable.
public int compareTo(Student st) {
return this.name.compareTo(st.name);
}
Ratik Singha; says
By Using Comparable interface .. You can sort on any field like name or tag etc… other than integer.
Just change the implementation of compareTo method like
@Override
public int compareTo(Student st) {
Student student = st;
return studentname.compareTo(student.getStudentName());
}
and from main method you can call
Collections.sort(Student);
..
So what is main requirement of Comparator interface…
Chandra Mauli Singh says
Thanks for explaining the topic. Just a little correction, As you highlighted, Using Comparable we can sort custom object only based on integer type. This is not correct, We can sort custom object on String base also, Like you shared Student Object above, having roll no, name and age, Let me show compareTo method performing sort based on String:
public int compareTo(Student compareStudent) {
return this.name.compareTo(compareStudent.name);
}
Above piece of code will sort Student object based on name (String Type).