-
Notifications
You must be signed in to change notification settings - Fork 4
Using Comparable VS Comparator
Comparable Interface
The comparable interface compares elements based on a single elements. This means that we need to override the compareTo method within the class that is implementing the comparable interface. We usually use comparable when we only want to sort something based on one attribute. For example, I only want to sort oranges based on sourness so I use comparable.
Comparator Interface
The comparator interface can compares elements based on multiple elements. We do not need to implement the Comparable interface in the class that is using the comparator. Instead, its best to create a separate class that implements the comparable interface and overrides the method compare. We usually use the comparator interface when we want to sort something based on many attributes or more than one condition. For example, I need to output two sorted lists of oranges, one sorted according to sourness the other according to cuteness. In this case, I need 2 comparators as a single compareTo method is not enough (and I can't have more than 1 compareTo methods)
Comparable | Comparator |
---|---|
Comparable provides a single sorting sequence. | The Comparator provides multiple sorting sequences. |
Comparable affects the original class, i.e., the actual class is modified. | Comparator doesn't affect the original class, i.e., the actual class is not modified. |
Comparable provides compareTo() method to sort elements. | Comparator provides compare() method to sort elements. |
Comparable is present in java.lang package. | A Comparator is present in the java.util package. |
We can sort the list elements of Comparable type by Collections.sort(List) method. | We can sort the list elements of Comparator type by Collections.sort(List, Comparator) method. |
Sort an Orange object based on its sourness-cuteness ratio.
class Orange {
// non-private for the sake of example
double cuteness;
double sourness;
Orange(double sourness, double cuteness) {
this.sourness = sourness;
this.cuteness = cuteness;
}
@Override
public String toString() {
return String.format("Orange with %f sourness-cuteness ratio", this.sourness / this.cuteness);
}
}
Modify the Orange class to make it comparable.
class Orange implements Comparable<Orange> {
// non-private for the sake of example
double cuteness;
double sourness;
Orange(double sourness, double cuteness) {
this.sourness = sourness;
this.cuteness = cuteness;
}
@Override
public int compareTo(Orange other) { // must return either 1 or -1 and 0 iff they are equal
if (this.sourness / this.cuteness > other.sourness / other.cuteness) {
return 1;
} else if (this.sourness / this.cuteness < other.sourness / other.cuteness) {
return -1;
} else {
return 0;
}
}
@Override
public String toString() {
return String.format("Orange with %f sourness-cuteness ratio", this.sourness / this.cuteness);
}
}
// Example run
orangesList.sort(null);
Use the original Orange class, but implement a new comparator class instead.
import java.util.Comparator;
class OrangeComparator implements Comparator<Orange> {
public int compare(Orange o1, Orange o2) {
return (int) (o1.sourness / o1.cuteness - o2.sourness / o2.cuteness);
}
}
// Example run
orangesList.sort(new OrangeComparator());
List<Orange> orangesList = new ArrayList<Orange>(Arrays.asList(
new Orange(7, 5), new Orange(6, 2), new Orange(-1, 2.5), new Orange(7, 4)));
Lets say you have an abstract class called "Fruit" an it has many subclasses like "Orange", "Durian", "Watermelon" etc. If you have many subclasses and want to rank each of them accordingly when sorting, you can use a HashMap to do so! For example, "Durian" is the king of fruits, so its always at the top of the stack, followed by "Oranges" second, "Watermelons" third etc.
class FruitComparator implements Comparator<Fruit> {
public int compare(Fruit fruit1, Fruit fruit2) {
Map<String, Integer> rankings = new HashMap<>();
rankings.put("Durian", 1);
rankings.put("Oranges", 2);
rankings.put("Watermelons", 3);
Integer fruit1Rank = rankings.get(fruit1.name);
Integer fruit2Rank = rankings.get(fruit2.name);
return fruit1Rank.compareTo(fruit2Rank);
}
}
Peer Learning
Guides
Setting Up Checkstyle
Setting Up Java
Setting Up MacVim
Setting Up Stu
Setting Up Unix For Mac
Setting Up Unix For Windows
Setting Up Vim
Setting up SSH Config
SSH Without Password
Copying Files From PE Nodes
Using tmux
CS2030 Contents
Lecture 1 SummaryLecture 2 Summary
Access Modifiers
Lecture 3 Summary (Polymorphism)
Compile Time Type VS Runtime Type
Abstraction, Encapsulation, Inheritance, and Polymorphism
SOLID Principles
Class VS Abstract Class VS Interface
Comparable VS Comparator
Generic Types T
HashMap
Raw Types with Generic
Lambda expression
PECS (Producer Extends Consumer Super)
Optional
Streams
Parallel Streams
Monad
Functors and Monads with Category Theory