1

It is generally said that comparator is used to have multiple sorting sequences of collection of objects while comparable is used to have single sorting sequence. What is the use of comparator interface in java when it is possible to have multiple sorting sequences using comparable interface?

import java.util.*;
enum CompareValue {RollNo, Marks;}
class Student implements Comparable<Student> {
    public int marks;
    public int rollNo;
    public static CompareValue comparator = CompareValue.RollNo;
    Student (int marks, int rollNo) {
        this.marks = marks;
        this.rollNo = rollNo;
    }
    public int compareTo(Student s) {
        switch (comparator) {
            case RollNo:
                return this.rollNo - s.rollNo;
            case Marks:
                return this.marks - s.marks;
        }
        return 0;
    }
}

public class Test
{
    public static void main (String[] args) 
    {
        Student s1 = new Student(59, 103);
        Student s2 = new Student(87, 102);
        Student s3 = new Student(78, 101);
        Student students[] = {s1, s2, s3};
        Arrays.sort(students);
        System.out.println("Student list sorted by rollno");
        for (Student s:students) {
            System.out.println(s.rollNo + " - " + s.marks);
        }
        Student.comparator = CompareValue.Marks;
        System.out.println("Student list sorted by marks");
        Arrays.sort(students);
        for (Student s:students) {
            System.out.println(s.rollNo + " - " + s.marks);
        }
    }
}
Ankit
  • 11
  • 1
  • Check if this answers your query https://stackoverflow.com/questions/1440134/when-should-a-class-be-comparable-and-or-comparator – J. P Mar 13 '19 at 07:21
  • Possible duplicate of [When should a class be Comparable and/or Comparator?](https://stackoverflow.com/questions/1440134/when-should-a-class-be-comparable-and-or-comparator) – Djensen Mar 13 '19 at 07:26
  • 1
    Your solution isn't thread safe. If you have two threads trying to sort different ways at the same time, it would throw an exception. You need to be very careful of mutable `static` fields, and as this is error prone it is often considered a hack. – Peter Lawrey Mar 13 '19 at 08:15

4 Answers4

1

When your compareTo method has different behaviors based on the value of some static variable, you are basically introducing a global setting that controls the natural ordering of the Student class.

This could be confusing and counter intuitive to users of your class.

Besides, it makes the implementation of compareTo awkward, especially if you have more than two implementations, and each implementation depends on multiple instance variables.

Comparator is a much more suitable interface to supply multiple different comparisons for instances of the same class, each implementation having its own compare() logic.

Eran
  • 387,369
  • 54
  • 702
  • 768
0

When you have objects that do not implement comparable, but you would like to sort a collection consisting them, you would either have to extend them just to sort your collection or provide a comparator that compares them even though they are not comparable.

Or you might want to compare sort those objects in a different manner then their natural sort.

Imagine such an example. String is an object that is comparable. Imagine you want to sort a collection of strings based on their hashCode instead of the string natural order. How would you do it without creating a comparator?

maslan
  • 2,078
  • 16
  • 34
0

What you have shown there is indeed multiple sort orders using Comparable, but don't you think it's too much boiler plate code? Let's say if you have added a new field to the class called name, and now you want to sort by name. You'd have to:

  • add a new case to the enum
  • add a new case to the compareTo.

Another disadvantage of using the approach you showed is that it is not necessarily clear what this means:

Arrays.sort(student);

You would have to look through your code and check what value you have set the comparator.

Also, if I were using your class and I want to sort by something else, I would have to create a Comparator anyway, because I can't edit your class.

But if you use Comparator, you solve all of these problems:

Arrays.sort(students, Comparator.comparing(Student::getName));

Therefore, Comparable is only useful when there is one natural order, like dates and times for example.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

If we look at the Comparable and Comparator interfaces and what they mean, everything will be clear.

Comparable:

This is an internal property of a JAVA class i.e. it assumes that whenever one uses the internal compareTo() method, one is using it for the specified object.

public int compareTo(T o);

Therefore, in implementation of this method we use this which is the current object and compare it to some other object of same type. These can be treated as defaults or use for natural ordering.
Like 1 comes before 2 and so on. This is the natural ordering.

Comparator:

This is property which actually is not tightly bound to the Java class itself. Comparators are used to actually provide a method to be used by some other services (like Collections.sort()) for achieving a particular goal.

int compare(T o1, T o2);

By this we mean, You can have multiple Comparators, providing different ways of achieving different goals wherein the actual service can pick any two objects and compare them.
This can be used to provide custom ordering, like using some equation we can come up with an ordering where f(1) actually comes after f(2) and so on. This equation will likely be achieving some order which solves a use-case.

swayamraina
  • 2,958
  • 26
  • 28