Comparable and Comparator in Java

V A S G ReddyV A S G Reddy
4 min read

Table of contents

In Java, Comparable and Comparator are two interfaces used for sorting objects. Here’s a detailed comparison of the two:

Comparable

  • Purpose: Defines the natural ordering of objects.

  • Method: compareTo(Object o)

  • Usage: Implemented by the class whose objects need to be ordered.

  • Single sorting sequence: Only one method, compareTo, can be implemented, meaning there is a single way to compare two objects.

  • Modification: Requires modifying the class to implement the Comparable interface, which means the source code of the class must be altered.

    Example:

      import java.util.ArrayList;
      import java.util.Collections;
      import java.util.List;
    
      class Student implements Comparable<Student> {
          private String name;
          private int rollNumber;
    
          public Student(String name, int rollNumber) {
              this.name = name;
              this.rollNumber = rollNumber;
          }
    
          @Override
          public int compareTo(Student other) {
              /* Sort by roll number
                -1 if current object < other object,
                  0 if the both objects are equal,
                  1 if the current object > other object
              */
              int result = this.rollNumber - other.rollNumber;
              return result;
          }
    
          @Override
          public String toString() {
              return "Student{" +
                      "name='" + name + '\'' +
                      ", rollNumber=" + rollNumber +
                      '}';
          }
      }
    
      public class Main {
          public static void main(String[] args) {
              List<Student> students = new ArrayList<>();
              students.add(new Student("Alice", 3));
              students.add(new Student("Bob", 1));
              students.add(new Student("Charlie", 2));
    
              Collections.sort(students);
    
              // Descending order
              // Collections.sort(students, Collections.reverseOrder());
    
              for (Student student : students) {
                  System.out.println(student);
              }
          }
      }
    

    Comparator

  • Purpose: Defines an external comparison strategy for objects.

  • Method: compare(Object o1, Object o2)

  • Usage: Implemented by a separate class to provide different ways of comparing objects.

  • Multiple sorting sequences: Can create multiple comparators to sort objects in different ways.

  • Modification: Does not require modifying the class whose instances are being compared. Instead, it provides a separate class to define the comparison logic.

Example:

import java.util.*;

public class Main {

    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 3, 20, 3.8));
        students.add(new Student("Bob", 1, 22, 3.6));
        students.add(new Student("Charlie", 2, 20, 3.9));
        students.add(new Student("David", 2, 21, 3.7));
        students.add(new Student("Eve", 2, 20, 3.9));

        // Sort by roll number (descending), name (ascending), age (ascending), GPA (descending)
        Collections.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int rollNumberComparison = Integer.compare(s2.getRollNumber(), s1.getRollNumber());
                if (rollNumberComparison != 0) {
                    return rollNumberComparison;
                }

                int nameComparison = s1.getName().compareTo(s2.getName());
                if (nameComparison != 0) {
                    return nameComparison;
                }

                int ageComparison = Integer.compare(s1.getAge(), s2.getAge());
                if (ageComparison != 0) {
                    return ageComparison;
                }

                return Double.compare(s2.getGpa(), s1.getGpa());
            }
        });

        System.out.println("Sorted by roll number (descending), name (ascending), age (ascending), GPA (descending):");
        for (Student student : students) {
            System.out.println(student);
        }
    }

    private static class Student {
        private String name;
        private int rollNumber;
        private int age;
        private double gpa;

        public Student(String name, int rollNumber, int age, double gpa) {
            this.name = name;
            this.rollNumber = rollNumber;
            this.age = age;
            this.gpa = gpa;
        }

        public String getName() {
            return name;
        }

        public int getRollNumber() {
            return rollNumber;
        }

        public int getAge() {
            return age;
        }

        public double getGpa() {
            return gpa;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", rollNumber=" + rollNumber +
                    ", age=" + age +
                    ", gpa=" + gpa +
                    '}';
        }
    }
}

Example: Using Lambda expressions.

import java.util.*;

class Student {
    private String name;
    private int rollNumber;
    private int age;
    private double gpa;

    public Student(String name, int rollNumber, int age, double gpa) {
        this.name = name;
        this.rollNumber = rollNumber;
        this.age = age;
        this.gpa = gpa;
    }

    public String getName() {
        return name;
    }

    public int getRollNumber() {
        return rollNumber;
    }

    public int getAge() {
        return age;
    }

    public double getGpa() {
        return gpa;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", rollNumber=" + rollNumber +
                ", age=" + age +
                ", gpa=" + gpa +
                '}';
    }
}

public class Main {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 3, 20, 3.8));
        students.add(new Student("Bob", 1, 22, 3.6));
        students.add(new Student("Charlie", 2, 20, 3.9));
        students.add(new Student("David", 2, 21, 3.7));
        students.add(new Student("Eve", 2, 20, 3.9));

        // Sort by roll number (descending), name (ascending), age (ascending), GPA (descending)
        students.sort(Comparator
                .comparing(Student::getRollNumber).reversed()
                .thenComparing(Student::getName)
                .thenComparing(Student::getAge)
                .thenComparing(Comparator.comparingDouble(Student::getGpa).reversed())
        );

        System.out.println("Sorted by roll number (descending), name (ascending), age (ascending), GPA (descending):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}
0
Subscribe to my newsletter

Read articles from V A S G Reddy directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

V A S G Reddy
V A S G Reddy