Sorting Java objects with Comparable and Comparator
Programmers frequently need to sort elements from a database into a collection, array, or map. In Java, we can implement whatever sorting algorithm we want with any type.
Using the Comparable interface and compareTo() method, we can sort using alphabetical order, String length, reverse alphabetical order, or numbers. The Comparator interface allows us to do the same but in a more flexible way.
Whatever we want to do, we just need to know how to implement the correct sort logic for the given interface and type.
Sorting with Java’s Comparable and Comparator interfaces
Here’s what you’ll learn in this article about sorting Java objects:
- Sorting with
Comparable:- Sorting a Java
List - How Java’s
compareTo()works - How to sort arrays in Java
- Sorting a Java
MapwithTreeMap - Sorting a Java
SetwithTreeSet - How to avoid
ClassCastExceptions when sorting - Using
Comparablewith the core Java classes
- Sorting a Java
- Sorting with
Comparator:- Using
Comparatorwith anonymous inner classes - Using
Comparatorwith lambda expressions
- Using
Sorting with Comparable
We’ll start with how to sort using Java’s Comparable interface. We use Comparable when there is a single, default comparison for the object we want sorted.
Sorting a Java List
In this first example, we implement Comparable in a Simpson class, using Simpson in the generic type:
class Simpson implements Comparable<Simpson> {
String name;
Simpson(String name) {
this.name = name;
}
@Override
public int compareTo(Simpson simpson) {
return this.name.compareTo(simpson.name);
}
}
public class SimpsonSorting {
public static void main(String... sortingWithList) {
List<SimpsonCharacter> simpsons = new ArrayList<>();
simpsons.add(new SimpsonCharacter("Homer "));
simpsons.add(new SimpsonCharacter("Marge "));
simpsons.add(new SimpsonCharacter("Bart "));
simpsons.add(new SimpsonCharacter("Lisa "));
Collections.sort(simpsons);
simpsons.stream().map(s -> s.name).forEach(System.out::print);
Collections.reverse(simpsons);
simpsons.stream().forEach(System.out::print);
}
}
Note that we’ve overridden the compareTo() method and passed in another Simpson object. We’ve also overridden the toString() method, just to make the example easier to read.
How Java’s compareTo() works
The compareTo() method compares a given object or the current instance with a specified object to determine the order of objects. Here’s a quick look at how compareTo() works.
We can only use classes that are comparable with the sort() method. If we try to pass a Simpson that does not implement Comparablewe will receive a compilation error.
The sort() method uses polymorphism by passing any object that is Comparable. Objects will then be sorted as expected.
The output from the previous code would be:
Bart Homer Lisa Marge
If we wanted to reverse the order, we could exchange the sort() for a reverse(); from:
Collections.sort(simpsons);
to:
Collections.reverse(simpsons);
Deploying the reverse() method would change the previous output to:
Marge Lisa Homer Bart
How to sort a Java array
In Java, we can sort an array with any type we want as long as it implements the Comparable interface. Here’s an example:
public class ArraySorting {
public static void main(String... moeTavern) {
int[] moesPints = new int[] {9, 8, 7, 6, 1};
Arrays.sort(moesPints);
Arrays.stream(moesPints).forEach(System.out::print);
Simpson[] simpsons = new Simpson[]{new Simpson("Lisa"), new Simpson("Homer")};
Arrays.sort(simpsons);
Arrays.stream(simpsons).forEach(System.out::println);
}
}
In the first sort() invocation, the array is sorted to:
1 6 7 8 9
In the second sort() invocation, it is sorted to:
Homer Lisa
Keep in mind that custom objects must implement Comparable in order to be sorted, even as an array.
How to avoid ClassCastExceptions when sorting Java objects
If the Simpson object wasn’t implementing Comparablea ClassCastException would be thrown. If you run this as a test, you will see something like the following output:
Error:(16, 20) java: no suitable method found for sort(java.util.List<com.javaworld.javachallengers.sortingcomparable.Simpson>)
method java.util.Collections.<T>sort(java.util.List<T>) is not applicable
(inference variable T has incompatible bounds
equality constraints: com.javaworld.javachallengers.sortingcomparable.Simpson
lower bounds: java.lang.Comparable<? super T>)
method java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<? super T>) is not applicable
(cannot infer type-variable(s) T
(actual and formal argument lists differ in length))
This log may be confusing, but don’t worry. Just keep in mind that a ClassCastException will be thrown for any sorted object that doesn’t implement the Comparable interface.
Sorting a Map with TreeMap
The Java API includes many classes to assist with sorting, including TreeMap. In the example below, we use TreeMap to sort keys into a Map.
public class TreeMapExample {
public static void main(String... barney) {
Map<SimpsonCharacter, String> simpsonsCharacters = new TreeMap<>();
simpsonsCharacters.put(new SimpsonCharacter("Moe"), "shotgun");
simpsonsCharacters.put(new SimpsonCharacter("Lenny"), "Carl");
simpsonsCharacters.put(new SimpsonCharacter("Homer"), "television");
simpsonsCharacters.put(new SimpsonCharacter("Barney"), "beer");
System.out.println(simpsonsCharacters);
}
}
TreeMap uses the compareTo() method implemented by the Comparable interface. Each element in the resulting Map is sorted by its key. In this case, the output would be:
Barney=beer, Homer=television, Lenny=Carl, Moe=shotgun
Remember, though: if the object doesn’t implement Comparableyou will get a ClassCastException.
Sorting a Set with TreeSet
The Set interface is responsible for storing unique values, but when we use the TreeSet implementation, inserted elements will be automatically sorted as we add them:
public class TreeSetExample {
public static void main(String... barney) {
Set<SimpsonCharacter> simpsonsCharacters = new TreeSet<>();
simpsonsCharacters.add(new SimpsonCharacter("Moe"));
simpsonsCharacters.add(new SimpsonCharacter("Lenny"));
simpsonsCharacters.add(new SimpsonCharacter("Homer"));
simpsonsCharacters.add(new SimpsonCharacter("Barney"));
System.out.println(simpsonsCharacters);
}
}
The output from this code is:
Barney, Homer, Lenny, Moe
Again, if we use an object that is not Comparablewe’ll get a ClassCastException.
TNG – Latest News & Reviews
