Java Comparable and Comparator Example to sort Objects
In Java, it’s very easy to sort an array or a list with primitive types. But you can also use Comparable
and Comparator
interfaces when you want to be able to short arrays or lists of your own custom objects.
Let’s begin with a very simple example using arrays of primitive types:
ObjectSortingExample.java
:
package com.javacodegeeks.java.core; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class ObjectSortingExample { public static void main(String[] args) { int[] integerArray = {1,0,3,2}; Arrays.sort(integerArray); System.out.println(Arrays.toString(integerArray)); String[] stringArray = {"J", "A", "V", "A", "C"}; Arrays.sort(stringArray); System.out.println(Arrays.toString(stringArray)); List stringList = new ArrayList(); stringList.add("J"); stringList.add("A"); stringList.add("V"); stringList.add("A"); stringList.add("C"); Collections.sort(stringList); for(String elem: stringList) System.out.print(" "+elem); } }
The output of this program will be:
[0, 1, 2, 3]
[A, A, C, J, V]
A A C J V
Now let’s try the same thing but with our own class.
Student.java
:
package com.javacodegeeks.java.core; public class Student { private int id; private String name; private int currentYearOfStudy; public Student(int id, String name, int currYearOfStudy) { this.id = id; this.name = name; this.currentYearOfStudy = currYearOfStudy; } public int getId() { return this.id; } public String getName() { return this.name; } public int getCurrentYearOfStudy() { return this.currentYearOfStudy; } }
ObjectSortingExample.java
:
package com.javacodegeeks.java.core; import java.util.Arrays; public class ObjectSortingExample { public static void main(String[] args) { Student[] studentArray = new Student[3]; studentArray[0] = new Student(1, "Nikos",1); studentArray[1] = new Student(5, "Ilias", 4); studentArray[2] = new Student(4, "Byron", 5); Arrays.sort(studentArray); System.out.println(Arrays.toString(studentArray)); } }
The output of this will be:
Exception in thread "main" java.lang.ClassCastException: com.javacodegeeks.java.core.Student cannot be cast to java.lang.Comparable
at java.util.ComparableTimSort.countRunAndMakeAscending(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at com.javacodegeeks.java.core.ObjectSortingExample.main(ObjectSortingExample.java:14)
And that is completely reasonable because Arrays.sort
method has no clue on how to compare my objects. Somehow we have to give Arrays.sort
a mechanism on how to compare my objects. To do that, we simply implement the generic Comparable<E>
interface and override the compareTo
method.
Student.java
:
package com.javacodegeeks.java.core; public class Student implements Comparable<Student> { private int id; private String name; private int currentYearOfStudy; public Student(int id, String name, int currYearOfStudy) { this.id = id; this.name = name; this.currentYearOfStudy = currYearOfStudy; } public int getId() { return this.id; } public String getName() { return this.name; } public int getCurrentYearOfStudy() { return this.currentYearOfStudy; } @Override public String toString() { return "[id=" + this.id + ", name=" + this.name + ", Current Year of Study=" + this.currentYearOfStudy + "]"; } @Override public int compareTo(Student stud) { return (this.id - stud.id); } }
ObjectSortingExample.java
:
package com.javacodegeeks.java.core; import java.util.Arrays; public class ObjectSortingExample { public static void main(String[] args) { Student[] studentArray = new Student[3]; studentArray[0] = new Student(1, "Nikos",1); studentArray[1] = new Student(5, "Ilias", 4); studentArray[2] = new Student(4, "Byron", 5); Arrays.sort(studentArray); System.out.println(Arrays.toString(studentArray)); } }
Now, as you might imagine, the Student will be sorted using the id
field as a key. So the output of the above program would be:
[[id=1, name=Nikos, Current Year of Study=1], [id=4, name=Byron, Current Year of Study=5], [id=5, name=Ilias, Current Year of Study=4]]
Now image that a client code “A” requires that Student
objects can be sorted using the name
as key and client code “B” requires that Student
objects can be sorted using currentYearOfStudy
. To do that we have to define different Comperators. We will do that inside the Student class but you can also create another separate class with your own Comperators.
Student.java
:
package com.javacodegeeks.java.core; import java.util.Comparator; public class Student implements Comparable<Student> { private int id; private String name; private int currentYearOfStudy; public Student(int id, String name, int currYearOfStudy) { this.id = id; this.name = name; this.currentYearOfStudy = currYearOfStudy; } public int getId() { return this.id; } public String getName() { return this.name; } public int getCurrentYearOfStudy() { return this.currentYearOfStudy; } @Override public String toString() { return "[id=" + this.id + ", name=" + this.name + ", Current Year of Study=" + this.currentYearOfStudy + "]"; } @Override public int compareTo(Student stud) { return (this.id - stud.id); } public static Comparator<Student> idComperator = new Comparator<Student>() { @Override public int compare(Student st1, Student st2) { return (int) (st1.getId() - st2.getId()); } }; public static Comparator<Student> currentYearComperator = new Comparator<Student>() { @Override public int compare(Student st1, Student st2) { return (int) (st1.getCurrentYearOfStudy() - st2.getCurrentYearOfStudy()); } }; }
ObjectSortingExample.java
:
package com.javacodegeeks.java.core; import java.util.Arrays; public class ObjectSortingExample { public static void main(String[] args) { Student[] studentArray = new Student[3]; studentArray[0] = new Student(1, "Nikos",1); studentArray[1] = new Student(5, "Ilias", 4); studentArray[2] = new Student(4, "Byron", 5); Arrays.sort(studentArray, Student.idComperator); System.out.println("Using id as key :"+ Arrays.toString(studentArray)); Arrays.sort(studentArray, Student.currentYearComperator); System.out.println("Using Current Year of Study as key :"+Arrays.toString(studentArray)); } }
The output of this program will be:
Using id as key :[[id=1, name=Nikos, Current Year of Study=1], [id=4, name=Byron, Current Year of Study=5], [id=5, name=Ilias, Current Year of Study=4]]
Using Current Year of Study as key :[[id=1, name=Nikos, Current Year of Study=1], [id=5, name=Ilias, Current Year of Study=4], [id=4, name=Byron, Current Year of Study=5]]
Of course you can further customize your Comperator and make it more complex. For example we will make a Comperator that will sort our objetc first by currentYearOfStudy
and then by name
:
Student.java
:
package com.javacodegeeks.java.core; import java.util.Comparator; public class Student implements Comparable<Student> { private int id; private String name; private int currentYearOfStudy; public Student(int id, String name, int currYearOfStudy) { this.id = id; this.name = name; this.currentYearOfStudy = currYearOfStudy; } public int getId() { return this.id; } public String getName() { return this.name; } public int getCurrentYearOfStudy() { return this.currentYearOfStudy; } @Override public String toString() { return "[id=" + this.id + ", name=" + this.name + ", Current Year of Study=" + this.currentYearOfStudy + "]"; } @Override public int compareTo(Student stud) { return (this.id - stud.id); } public static Comparator<Student> idComperator = new Comparator<Student>() { @Override public int compare(Student st1, Student st2) { return (int) (st1.getId() - st2.getId()); } }; public static Comparator<Student> currentYearComperator = new Comparator<Student>() { @Override public int compare(Student st1, Student st2) { return (int) (st1.getCurrentYearOfStudy() - st2 .getCurrentYearOfStudy()); } }; public static Comparator<Student> currentYearandNameComperator = new Comparator<Student>() { @Override public int compare(Student st1, Student st2) { int retval = (int) (st1.getCurrentYearOfStudy() - st2.getCurrentYearOfStudy()); if (retval == 0) { retval = (int) (st1.getName().compareTo(st2.getName())); } return retval; } }; }
ObjectSortingExample.java
:
package com.javacodegeeks.java.core; import java.util.Arrays; public class ObjectSortingExample { public static void main(String[] args) { Student[] studentArray = new Student[3]; studentArray[0] = new Student(1, "Nikos",5); studentArray[1] = new Student(5, "Ilias", 4); studentArray[2] = new Student(4, "Byron", 4); Arrays.sort(studentArray, Student.currentYearAndNameComperator); System.out.println("Using Current Year and Name as key :"+ Arrays.toString(studentArray)); } }
The output of this program will be:
Using Current Year and Name as key :[[id=4, name=Byron, Current Year of Study=4], [id=5, name=Ilias, Current Year of Study=4], [id=1, name=Nikos, Current Year of Study=5]]
This was a Comparable and Comparator Example to sort Objects in Java.