The Collections
class offers two standard static methods to sort a list:
sort(List<T> list)
applicable to lists where T extends Comparable<? super T>
, andsort(List<T> list, Comparator<? super T> c)
applicable to lists of any type.Applying the former requires amending the class of list elements being sorted, which is not always possible. It might also be undesirable as although it provides the default sorting, other sorting orders may be required in different circumstances, or sorting is just a one off task.
Consider we have a task of sorting objects that are instances of the following class:
public class User {
public final Long id;
public final String username;
public User(Long id, String username) {
this.id = id;
this.username = username;
}
@Override
public String toString() {
return String.format("%s:%d", username, id);
}
}
In order to use Collections.sort(List<User> list)
we need to modify the User
class to implement the Comparable
interface. For example
public class User implements Comparable<User> {
public final Long id;
public final String username;
public User(Long id, String username) {
this.id = id;
this.username = username;
}
@Override
public String toString() {
return String.format("%s:%d", username, id);
}
@Override
/** The natural ordering for 'User' objects is by the 'id' field. */
public int compareTo(User o) {
return id.compareTo(o.id);
}
}
(Aside: many standard Java classes such as String
, Long
, Integer
implement the Comparable
interface. This makes lists of those elements sortable by default, and simplifies implementation of compare
or compareTo
in other classes.)
With the modification above, the we can easily sort a list of User
objects based on the classes natural ordering. (In this case, we have defined that to be ordering based on id
values). For example:
List<User> users = Lists.newArrayList(
new User(33L, "A"),
new User(25L, "B"),
new User(28L, ""));
Collections.sort(users);
System.out.print(users);
// [B:25, C:28, A:33]
However, suppose that we wanted to sort User
objects by name
rather than by id
. Alternatively, suppose that we had not been able to change the class to make it implement Comparable
.
This is where the sort
method with the Comparator
argument is useful:
Collections.sort(users, new Comparator<User>() {
@Override
/* Order two 'User' objects based on their names. */
public int compare(User left, User right) {
return left.username.compareTo(right.username);
}
});
System.out.print(users);
// [A:33, B:25, C:28]
In Java 8 you can use a lambda instead of an anonymous class. The latter reduces to a one-liner:
Collections.sort(users, (l, r) -> l.username.compareTo(r.username));
Further, there Java 8 adds a default sort
method on the List
interface, which simplifies sorting even more.
users.sort((l, r) -> l.username.compareTo(r.username))