When to use Comparable and Comparator
I would say that an object should implement Comparable if that is the clear natural way to sort the class, and anyone would need to sort the class would generally want to do it that way.
If, however, the sorting was an unusual use of the class, or the sorting only makes sense for a specific use case, then a Comparator is a better option.
Put another way, given the class name, is it clear how a comparable would sort, or do you have to resort to reading the javadoc? If it is the latter, odds are every future sorting use case would require a comparator, at which point the implementation of comparable may slow down users of the class, not speed them up.
Why use comparable and comparator interface
A question such as "why use Comparator
or Comparable
rather than bubble sort?" really makes no sense. These are not alternatives to each other. Any sorting algorithm (including ones that you code yourself) needs a mechanism for defining the order of the objects. That is what the interfaces do: provide a mechanism for defining an ordering on objects.
If the question is "why use sorting methods built into the JDK rather than write your own?" then the answer is probably fairly obvious: it saves effort and complexity.
If the question is "when should you use Comparable
and when should you use Comparator
?" then I would suggest searching for one of the excellent primers on this topic. As a very simplified answer, Comparable
is used to define a natural (default) ordering for objects within a class while Comparator
is used to define a custom ordering to be passed to a method.
Note also that the Comparator
interface has many very powerful methods for defining comparisons. Very little needs to be done manually now. For example, if you have a Person
class you can sort a list with code such as:
Collection.sort(personList, Comparator
.comparingInt(Person::getAge)
.thenComparing(Person::getSurname));
In my view this code is better than the old mechanism of defining compareTo
methods in a class as it hides away the implementation details of returning arbitrary integers representing comparison between fields and makes the intention pretty obvious. In fact it's enough of an improvement on older methods that in my own code I tend to avoid natural orderings altogether unless the class has an inherent obvious order that can be naturally represented as the difference between two integers (e.g. a class defining temperature or heights).
When should I use Comparator vs Comparable?
There's a substantial distinction between the use cases for Comparator
and Comparable
.
Implementing the Comparable
interface is suitable for objects that have a natural order in your domain model. I'm not sure whether animals have a natural order, but if it is the case from the perspective of how your application model the animals, that's fine - that's the way to go. Otherwise, your class should not implement Comparable
.
It's not something opinion-based, documentation clearly defines when these interfaces are intended to be used.
Comparable:
This interface imposes a total ordering on the objects of each class
that implements it. This ordering is referred to as the class's
natural ordering, and the class'scompareTo
method is referred to as
its natural comparison method.
Comparator:
Comparators can also be used to control the order of certain data structures (such as sorted sets or sorted maps), or to provide an ordering for collections of objects that don't have a natural ordering.
Another obvious distinction, that you can define as many flavors of comparators as you need. Which is handy when there's no one specific way to compare and sort the objects. And they must have more meaningful names than comparator
.
Personally, I don't see a huge harm in defining a couple of comparators as public static final
fields, as in your example. If you have a single class that manages the instances of this type - extract the comparators into that class, otherwise if these objects are ubiquitous and used in many places you can leave them right inside the POJO (that an opinion based part).
Difference between Comparable and Comparator?
Not really.Comparable
and Comparator
are generic interfaces that allow to compare instances of the type defined in the generic (subclasses included).
The main difference between them is that Comparable
is directly implemented in the class which you want to compare objects.
Consequently, if you have a single way to compare instances from a class, that is that you have a natural order for them, Comparable
is the right approach.
On the other hand, if you have multiple ways to compare instances from a class, Comparable
is not enough.
You should use Comparator
s instead (if it doesn't exist a natural order) or use both (if it exists a natural order and some other kinds of order).
Example where Comparator
can be useful in addition to Comparable
:
The String
class implements Comparable
by comparing two strings lexicographically.
Suppose you need to sort a List
of String
according to a different rule : their length.
You will need to define a Comparator<String>
that implements this rule such as :
public class StringLengthComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
return Integer.compare(o1.length(), o2.length());
}
}
Now you could sort String
s by using their natural order (using Comparable
) :
List<String> strings = new ArrayList<>();
...
strings.sort();
But you could also use a specific Comparator<String>
:
strings.sort(new StringLengthComparator());
Or without creating any class with a lambda:
strings.sort((o1,o2)->Integer.compare(o1.length(), o2.length()));
Example where Comparator
should be used instead of Comparable
:
Suppose you have an Account
class that represents a bank account.
Functionally you don't have a natural order to sort them but you have instead multiple orders according to the client needs.
Making the class to implement Comparable
would not make sense. But creating distinct Comparator<Account>
would.
Case where only Comparator
can be used :
If you want to define a order for instances of a class which you cannot change the source code (JDK class or third party class), Comparator
is the way to follow.
Java: Comparable vs Comparator - Memory & Performance
That answer is incorrect.
Adding implemented interfaces or methods does not influence the memory required for individual instances of a class.
First of all, conceptually it doesn't make sense.
Implemented interfaces and methods are per-class information. Two instances of the same class will always implement exactly the same interfaces and have the exact same methods. As such, it makes no sense for the JVM to store that information per-object.
Second, you can easily verify that with sample code like this:
public class MyClass implements Comparable<MyClass> {
private final long l;
MyClass(long l) {this.l = l;}
@Override
public int compareTo(MyClass o) {
return 0;
}
public static void main(String[] args) {
long l = 0;
try {
var list = new ArrayList<MyClass>();
while (true) {
list.add(new MyClass(l++));
}
} catch (OutOfMemoryError e) {
System.out.println("Created " + l + " objects before things went south ...");
}
}
}
Running this with -Xmx32m
using Java 11 will create about 200000 objects on each run for me (with slight variations, probably due to GC details).
Removing the Comparable
interface and/or the compareTo
method does not significantly change that value.
You can try adding additional fields or removing l
, which will change the number.
Java : Comparable vs Comparator
When your class implements Comparable, the compareTo
method of the class is defining the "natural" ordering of that object. That method is contractually obligated (though not demanded) to be in line with other methods on that object, such as a 0 should always be returned for objects when the .equals()
comparisons return true.
A Comparator is its own definition of how to compare two objects, and can be used to compare objects in a way that might not align with the natural ordering.
For example, Strings are generally compared alphabetically. Thus the "a".compareTo("b")
would use alphabetical comparisons. If you wanted to compare Strings on length, you would need to write a custom comparator.
In short, there isn't much difference. They are both ends to similar means. In general implement comparable for natural order, (natural order definition is obviously open to interpretation), and write a comparator for other sorting or comparison needs.
When should a class be Comparable and/or Comparator?
The text below comes from Comparator vs Comparable
Comparable
A comparable object is capable of comparing itself with another object. The class itself must implements the java.lang.Comparable
interface in order to be able to compare its instances.
Comparator
A comparator object is capable of comparing two different objects. The class is not comparing its instances, but some other class’s instances. This comparator class must implement the java.util.Comparator
interface.
Related Topics
Http Basic Authentication in Java Using Httpclient
Gson Serialize a List of Polymorphic Objects
Does the Jvm Prevent Tail Call Optimizations
How to Retrieve Element Value of Xml Using Java
How to Create an .Exe for a Java Program
Java:If a Extends B and B Extends Object, Is That Multiple Inheritance
Why Would One Mark Local Variables and Method Parameters as "Final" in Java
Using Mockito to Test Abstract Classes
Is It Good Practice to Use Java.Lang.String.Intern()
How to Bundle a Native Library and a Jni Library Inside a Jar
Convert Float to String and String to Float in Java
Understanding the Workings of Equals and Hashcode in a Hashmap
How to Use a Wildcard in the Classpath to Add Multiple Jars
How to Convert Currenttimemillis to a Date in Java
Casting Object Array to Integer Array Error
What Does the Question Mark in Java Generics' Type Parameter Mean