Java 集合排序

更新于 2025-12-25

Jakob Jenkov 2020-10-04

你可以使用 java.util.Collections.sort() 方法对 Java 的 List 集合进行排序。以下两种 List 类型都可以被排序:

  • ArrayList
  • LinkedList

按自然顺序对对象排序

要对一个 List 进行排序,可以这样做:

List list = new ArrayList();
// 向列表中添加元素
Collections.sort(list);

以这种方式排序时,元素将按照其“自然顺序”(natural order)进行排列。为了让对象具有自然顺序,它们必须实现 java.lang.Comparable 接口。有关 Comparable 接口的更多信息,请参阅 Java Comparable 教程。换句话说,这些对象必须是可比较的,才能确定它们的顺序。

以下是 Comparable 接口的定义:

public interface Comparable<T> {
    int compareTo(T o);
}

compareTo() 方法应将当前对象与另一个对象进行比较,并返回一个 int 值。该返回值需遵循以下规则:

  • 如果当前对象小于另一个对象,则返回一个负数;
  • 如果当前对象等于另一个对象,则返回 0;
  • 如果当前对象大于另一个对象,则返回一个正数。

在实现 compareTo() 方法时还有其他一些更具体的要求,但以上是主要规则。详细信息请查阅 Java 官方文档(JavaDoc)。

举个例子,假设你正在对一个包含 String 元素的 List 进行排序。排序过程中,每个字符串会通过某种排序算法(此处不展开)与其他字符串进行比较。每个字符串通过字母顺序来比较自身与其他字符串的大小。因此,如果一个字符串按字母顺序小于另一个字符串,它的 compareTo() 方法就会返回一个负数。

当你在自己的类中实现 compareTo() 方法时,你需要决定这些对象应该如何相互比较。例如,Employee 对象可以按名字、姓氏、薪资、入职年份等任何你认为合理的属性进行比较。


使用 Comparator 对象进行排序

有时,你可能希望按照不同于自然顺序的方式对列表进行排序。或者,你所排序的对象甚至没有自然顺序。在这种情况下,你可以使用 Comparator。有关 Comparator 接口的更多信息,请参阅 Java Comparator 教程

以下是使用 Comparator 对列表排序的方法:

List list = new ArrayList();
// 向列表中添加元素
Comparator comparator = new SomeComparator();
Collections.sort(list, comparator);

注意,现在 Collections.sort() 方法除了接收 List 外,还额外接收一个 java.util.Comparator 参数。这个 Comparator 会逐一比较列表中的元素。

以下是 Comparator 接口的定义:

public interface Comparator<T> {
    int compare(T object1, T object2);
}

compare() 方法用于比较两个对象,应遵循以下规则:

  • 如果 object1 小于 object2,返回一个负数;
  • 如果 object1 等于 object2,返回 0;
  • 如果 object1 大于 object2,返回一个正数。

同样,compare() 方法的实现还有一些额外要求,但上述是核心规则。更多细节请参考 JavaDoc。

下面是一个比较两个虚构 Employee 对象的 Comparator 示例:

public class MyComparator<Employee> implements Comparator<Employee> {
    public int compare(Employee emp1, Employee emp2) {
        if (emp1.getSalary() < emp2.getSalary()) return -1;
        if (emp1.getSalary() == emp2.getSalary()) return 0;
        return 1;
    }
}

一种更简洁的写法如下:

public class MyComparator<Employee> implements Comparator<Employee> {
    public int compare(Employee emp1, Employee emp2) {
        return emp1.getSalary() - emp2.getSalary();
    }
}

通过将一个薪资减去另一个薪资,结果会自动为负数、0 或正数。是不是很巧妙?

如果你需要根据多个因素对对象进行比较,可以先按第一个因素(如名字)比较;如果第一个因素相等,再按第二个因素(如姓氏或薪资)比较,依此类推。