排序通用列表

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 类,如 StringLongInteger 实现了 Comparable 接口。这使得这些元素的列表默认可排序,并简化了 comparecompareTo 在其他类中的实现。)

通过上面的修改,我们可以根据类自然排序轻松地对 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 而不是 idUser 对象进行排序。或者,假设我们无法更改类以使其实现 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))