Introduction
Comparing objects and sorting them is a common requirement in many applications. Java provides two interfaces, Comparator
and Comparable
, that are used to allow classes to define their own natural order based on some criteria.
Comparing objects and sorting them is a common requirement in many applications. Java provides two interfaces, Comparator
and Comparable
, that are used to allow classes to define their own natural order based on some criteria.
Comparable
interfaceTo implement the Comparable
interface, the class needs to define its natural ordering. This is done by overriding the compareTo()
method. The compareTo()
method returns a negative integer, zero, or a positive integer if the calling object is less than, equal to, or greater than the method's argument.
The following code block provides an example of a Student
class implementing the Comparable
interface:
class Student implements Comparable<Student> {
private String name;
private int gpa;
private int regNo;
public Student(String name, int gpa, int regNo) {
this.name = name;
this.gpa = gpa;
this.regNo = regNo;
}
// Override the compareTo() method
@Override
public int compareTo(Student other) {
return this.gpa - other.gpa;
}
// Getters and setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGpa() {
return gpa;
}
public void setGpa(int gpa) {
this.gpa = gpa;
}
public int getRegNo() {
return regNo;
}
public void setRegNo(int regNo) {
this.regNo = regNo;
}
}
In the compareTo()
method, we define the ordering based on the gpa
of the students.
Collections.sort()
methodWith the compareTo()
method in place, we can sort a list of Student
objects using the Collections.sort()
method. The following code block provides an example of this:
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
Collections.sort(studentList);
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
The Collections.sort()
method sorts the Student
objects in the list based on their gpa
in ascending order using the compareTo()
method.
Comparator
interfaceIn some cases, you may want to sort objects based on different criteria. In such cases, we can use the Comparator
interface.
The Comparator
interface provides a compare()
method that takes two arguments and returns a negative integer, zero, or a positive integer if the first argument is less than, equal to, or greater than the second.
Here is an example of a Student
class with a Comparator
interface implementation to sort by name:
class StudentNameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
}
Comparator
To use a Comparator
to sort objects, the sort()
method of the Collections
class is used. The sort()
method has an overloaded version that accepts an additional argument of type Comparator
.
Here is an example of using the StudentNameComparator
class to sort Student
objects by name:
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
StudentNameComparator nameComparator = new StudentNameComparator();
Collections.sort(studentList, nameComparator);
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
The Collections.sort()
method uses the nameComparator
object to sort Student
objects based on their names in alphabetical order.
In some cases, you may want to sort objects by multiple criteria. For example, you may want to sort Student
objects first by their gpa
, then by their names.
You can do this by chaining multiple comparators using the thenComparing()
method of the Comparator
interface.
Here's an example of a Student
class with a comparator that sorts by gpa and then name:
class StudentGpaNameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
int gpaCompare = s1.getGpa() - s2.getGpa();
if (gpaCompare != 0) {
return gpaCompare;
}
return s1.getName().compareTo(s2.getName());
}
}
The StudentGpaNameComparator
class compares Student
objects based on their gpa
. If the gpa
is the same, it breaks the tie by comparing the Student
objects based on their names.
thenComparing()
To sort objects by multiple criteria, use the thenComparing()
method of the Comparator
interface. The thenComparing()
method takes a Comparator
object as a parameter and returns a new Comparator
object that chains the previous Comparator
with the new one.
Here's an example of how to sort Student
objects using the StudentGpaNameComparator
class:
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
studentList.add(new Student("Joe", 4, 104));
StudentGpaNameComparator gpaNameComparator = new StudentGpaNameComparator();
Collections.sort(studentList, gpaNameComparator);
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
The Collections.sort()
method uses the gpaNameComparator
object to sort Student
objects based on their gpa
and then according to their names.
By default, the Collections.sort()
method sorts objects in ascending order. To sort objects in descending order, use the reverseOrder()
method of the Comparator
interface. This method returns a Comparator
object that orders objects in the reverse order of their natural order.
Here's an example of sorting Student
objects by GPA in descending order:
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
studentList.add(new Student("Joe", 4, 104));
Comparator<Student> reverseGpaComparator = Collections.reverseOrder();
Collections.sort(studentList, new StudentGpaComparator().thenComparing(new StudentNameComparator()).reversed());
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
The reverseGpaComparator
object is used to sort Student
objects in descending order of their gpa
. The thenComparing()
method is used to sort Student
objects by name as a tiebreaker. Finally, the reversed()
method is used to reverse the order of the entire comparison.
Now that you know how to sort objects using Comparable
and Comparator
, let's put everything together in a single Java class:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Student implements Comparable<Student> {
private String name;
private int gpa;
private int regNo;
public Student(String name, int gpa, int regNo) {
this.name = name;
this.gpa = gpa;
this.regNo = regNo;
}
// Override compareTo() for natural ordering
@Override
public int compareTo(Student other) {
return this.gpa - other.gpa;
}
// Getters and setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGpa() {
return gpa;
}
public void setGpa(int gpa) {
this.gpa = gpa;
}
public int getRegNo() {
return regNo;
}
public void setRegNo(int regNo) {
this.regNo = regNo;
}
}
class StudentNameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
}
class StudentGpaComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return s1.getGpa() - s2.getGpa();
}
}
class StudentGpaNameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
int gpaCompare = s1.getGpa() - s2.getGpa();
if (gpaCompare != 0) {
return gpaCompare;
}
return s1.getName().compareTo(s2.getName());
}
}
public class ComparatorComparable {
public static void main(String[] args) {
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
studentList.add(new Student("Joe", 4, 104));
// Sort by GPA using compareTo()
Collections.sort(studentList);
System.out.println("Sorting by GPA:");
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
// Sort by name using Comparator
StudentNameComparator nameComparator = new StudentNameComparator();
Collections.sort(studentList, nameComparator);
System.out.println("\nSorting by name:");
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
// Sort by GPA and then name using Comparator chaining
StudentGpaNameComparator gpaNameComparator = new StudentGpaNameComparator();
Collections.sort(studentList, gpaNameComparator);
System.out.println("\nSorting by GPA and then name:");
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
// Sort by GPA in descending order and then name in ascending order using Comparator chaining
Comparator<Student> reverseGpaComparator = Collections.reverseOrder();
Collections.sort(studentList, new StudentGpaComparator().thenComparing(new StudentNameComparator()).reversed());
System.out.println("\nSorting by GPA in descending order and then name in ascending order:");
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
}
}
To run the code samples, save the file as ComparatorComparable.java
and run the following commands in your terminal:
cd ~/project
javac ComparatorComparable.java
java ComparatorComparable
You should see the output from the sorted Student
objects based on the different sorting criteria.
In this lab, you learned how to use the Comparable
and Comparator
interfaces in Java to sort objects based on different criteria.
Specifically, you learned how to implement the Comparable
interface to define natural ordering based on a class's criteria. You also learned how to use the Comparator
interface to define ordering based on different criteria and chain multiple comparators.
Finally, you learned how to sort objects using the Collections.sort()
method and how to sort objects in descending order using the reverseOrder()
method.