Java集合框架提供了丰富的集合类用于存储和操作数据,排序是集合操作中非常常见的需求。集合框架的排序能力依托于比较器机制实现,开发者可以通过内置的比较规则或者自定义比较逻辑,满足不同的排序场景。

集合排序的两种核心方式
Java集合框架的排序主要分为自然排序和定制排序两种模式,二者的核心区别在于排序规则的来源不同。
自然排序
自然排序要求集合中的元素实现Comparable接口,重写其中的compareTo方法,定义元素默认的排序规则。当调用集合的排序方法时,会直接使用元素自身的排序逻辑进行比较。
比如Java中的Integer、String等包装类都已经默认实现了Comparable接口,因此可以直接对包含这些类型的集合进行排序。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class NaturalSortDemo {
public static void main(String[] args) {
List<Integer> numList = new ArrayList<>();
numList.add(3);
numList.add(1);
numList.add(2);
// 自然排序,Integer默认升序
Collections.sort(numList);
System.out.println(numList); // 输出 [1, 2, 3]
}
}
定制排序
定制排序不需要元素本身实现排序接口,而是通过传入一个Comparator比较器对象,临时定义排序规则。这种方式更加灵活,可以在不修改元素类定义的前提下,实现多种不同的排序逻辑。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CustomSortDemo {
public static void main(String[] args) {
List<Integer> numList = new ArrayList<>();
numList.add(3);
numList.add(1);
numList.add(2);
// 定制排序,传入Comparator实现降序
Collections.sort(numList, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// 返回值小于0表示o1排在o2前面,大于0表示o1排在o2后面,等于0表示二者相等
return o2 - o1;
}
});
System.out.println(numList); // 输出 [3, 2, 1]
}
}
Comparable与Comparator的区别
这两个接口都是用于定义比较规则的,但是使用场景和设计目的有明显差异,具体对比如下:
| 对比维度 | Comparable | Comparator |
|---|---|---|
| 所在包 | java.lang | java.util |
| 排序类型 | 自然排序,默认排序规则 | 定制排序,临时排序规则 |
| 核心方法 | compareTo(T o) | compare(T o1, T o2) |
| 修改要求 | 需要修改元素类的源码实现接口 | 不需要修改元素类,外部传入比较器即可 |
| 灵活性 | 较低,每个类只能有一种默认排序规则 | 较高,可以定义多个不同的比较器实现多种排序 |
自定义类的排序实现
实际开发中经常会遇到自定义实体类的排序需求,比如有一个用户类,需要按照年龄或者姓名进行排序,可以通过两种方式实现。
方式一:实现Comparable接口
在自定义类中实现Comparable接口,定义默认的排序规则,比如按照年龄升序排序。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
// 自定义用户类,实现Comparable接口
class User implements Comparable<User> {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// 重写compareTo方法,定义默认排序规则:按年龄升序
@Override
public int compareTo(User o) {
return this.age - o.age;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User("张三", 20));
userList.add(new User("李四", 18));
userList.add(new User("王五", 22));
// 自然排序,按照年龄升序
Collections.sort(userList);
System.out.println(userList);
// 输出 [User{name='李四', age=18}, User{name='张三', age=20}, User{name='王五', age=22}]
}
}
方式二:使用Comparator比较器
如果不想修改User类的源码,或者需要按照姓名进行排序,可以使用Comparator比较器,定义临时的排序规则。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
public class ComparatorSortDemo {
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User("张三", 20));
userList.add(new User("李四", 18));
userList.add(new User("王五", 22));
// 使用Comparator按姓名升序排序
Collections.sort(userList, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getName().compareTo(o2.getName());
}
});
System.out.println(userList);
// 输出 [User{name='李四', age=18}, User{name='王五', age=22}, User{name='张三', age=20}]
// Java 8之后可以使用lambda简化Comparator的写法
Collections.sort(userList, (u1, u2) -> u2.getAge() - u1.getAge());
System.out.println(userList);
// 输出 [User{name='王五', age=22}, User{name='张三', age=20}, User{name='李四', age=18}]
}
}
排序的注意事项
- 如果使用
TreeSet、TreeMap等有序集合,元素必须要么实现Comparable接口,要么在创建集合时传入Comparator比较器,否则会抛出类型转换异常。 compare和compareTo方法的返回值需要符合约定:返回负数表示第一个参数应该排在第二个参数之前,返回正数表示第一个参数排在第二个参数之后,返回0表示两个参数相等。- 如果排序规则中存在多个排序条件,比如先按年龄排序,年龄相同再按姓名排序,可以在比较器中依次判断多个条件。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
public class MultiConditionSort {
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User("张三", 20));
userList.add(new User("李四", 18));
userList.add(new User("王五", 20));
userList.add(new User("赵六", 18));
// 多条件排序:先按年龄升序,年龄相同按姓名升序
Collections.sort(userList, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
// 先比较年龄
int ageCompare = o1.getAge() - o2.getAge();
if (ageCompare != 0) {
return ageCompare;
}
// 年龄相同再比较姓名
return o1.getName().compareTo(o2.getName());
}
});
System.out.println(userList);
// 输出 [User{name='赵六', age=18}, User{name='李四', age=18}, User{name='张三', age=20}, User{name='王五', age=20}]
}
}
Java集合框架排序比较器Comparator修改时间:2026-06-13 14:24:19