排序通用列表
Collections
类提供了两种标准静态方法来对列表进行排序:
sort(List<T> list)
适用于T extends Comparable<? super T>
和sort(List<T> list, Comparator<? super T> c)
适用于任何类型的列表。
应用前者需要修改被排序的列表元素的类,这并不总是可行的。它也可能是不合需要的,因为虽然它提供默认排序,但在不同情况下可能需要其他排序顺序,或者排序只是一次性任务。
考虑我们有一个排序对象的任务,这些对象是以下类的实例:
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);
}
}
为了使用 Collections.sort(List<User> list)
,我们需要修改 User
类来实现 Comparable
接口。例如
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);
}
}
(旁白:许多标准的 Java 类,如 String
,Long
,Integer
实现了 Comparable
接口。这使得这些元素的列表默认可排序,并简化了 compare
或 compareTo
在其他类中的实现。)
通过上面的修改,我们可以根据类自然排序轻松地对 User
对象列表进行排序。 (在这种情况下,我们已经定义了基于 id
值的排序)。例如:
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]
但是,假设我们想要通过 name
而不是 id
对 User
对象进行排序。或者,假设我们无法更改类以使其实现 Comparable
。
这是使用 Comparator
参数的 sort
方法有用的地方:
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]
Version >= Java SE 8
在 Java 8 中,你可以使用 lambda 而不是匿名类。后者减少为单线:
Collections.sort(users, (l, r) -> l.username.compareTo(r.username));
此外,Java 8 在 List
接口上添加了默认的 sort
方法,这进一步简化了排序。
users.sort((l, r) -> l.username.compareTo(r.username))