Comparable and Comparator
When objects need an order
Numbers and strings already have an obvious order, but for custom objects Java cannot guess
what should count as “smaller” or “larger.” The same object might be compared by name, price, date, or any other property.
Comparable and Comparator are used to describe ordering.
Comparable: the natural order of a class
If a class has one primary, natural way to be ordered, it can implement
Comparable<T> and the compareTo() method.
class Level implements Comparable<Level> {
private final int value;
Level(int value) {
this.value = value;
}
@Override
public int compareTo(Level other) {
return Integer.compare(value, other.value);
}
}
A comparison result below zero means “this object comes before,” zero means the same position in the ordering,
and a result above zero means “this object comes after.” You do not need to return exactly -1,
0, or 1: the sign of the result is what matters.
Comparator: a separate comparison rule
When there are several useful orderings or the class cannot be changed, the rule is moved into a
Comparator<T>.
class LengthComparator implements Comparator<String> {
@Override
public int compare(String left, String right) {
return Integer.compare(left.length(), right.length());
}
}
List<String> names = new ArrayList<>(List.of("Bob", "Alexander", "Ann"));
names.sort(new LengthComparator());
Now the strings are sorted by length, while their own natural ordering remains alphabetical. This lets you keep several independent comparison rules for one type.
Natural and reverse order
For types that already implement Comparable, the standard library provides ready-made comparators.
List<Integer> numbers = new ArrayList<>(List.of(3, 1, 2));
numbers.sort(Comparator.naturalOrder());
numbers.sort(Comparator.reverseOrder());
equals(),
some structures and algorithms may behave unexpectedly. Such a mismatch should be deliberate.