Java: Never Implement Comparable
Java traditionally offers two ways to do this: the Comparable
interface and separate Comparator
classes. We argue that Comparable
is a bad design idea in Java and should never be implemented.
Consider the following class definition of a User
entity:
1 2 3 4 5 6 7 8 9 10 11 |
public class User implements Comparable<User> { private long id; private String name; private ZonedDateTime registrationDate; public int compareTo(User o) { return name.compareTo(o.name); } } |
Here we implemented Comparable
, implying that users are “naturally” sorted by name. This seems to make sense as long as only this order is important. However, User::compareTo
describes a relation between users, not a property of a single user. There will be different compareTo
relations down the road.
What if, for example, another feature requires that we show users sorted by registrationDate
? We cannot just implement Comparable
twice, so now we have to implement a Comparator
for registrationDate
. But why would we treat the implementations of the two orders differently? To maintain consistency we have to move the comparison by name to its own Comparator
.
Also consider this client code: does Collections.sort(users)
sort by name
or registrationDate
? The order is important for the context in which the users
collection is used. Implementing Comparable
hides that information away in the User
class. Using a Comparator
explicitly would look like this:
1 2 |
Comparator ascendingByName = Comparator.comparing(User::getUsername); Collections.sort(users, ascendingByName); |
To Collections.sort()
, a Comparator
is a strategy class that tells it how to order things. Keeping the order relation separated is just good design and leads to more readable code. Now it is easy to implement other comparisons:
1 2 3 4 5 |
// sort users descending by name users.sort(ascendingByName.reversed()); // sort users by registration date Comparator byRegistrationDate = Comparator.comparing(User::getRegistrationDate); users.sort(byRegistrationDate); |
Here we made use of the new Java 8 default method Collection::sort
, which allows us to simply write users.sort(...)
. Interestingly, it has a mandatory parameter of type Comparator
. It doesn’t even give us the choice to use Comparable
! It is difficult to tell if this was a conscious design decision on part of the Java language designers. We think it’s a good decision nonetheless.
Recent posts






Comment article