优先用comparable定义对象天然、稳定的默认排序,如string按字典序;多变、临时或第三方类排序则用comparator。一个类仅能实现一个compareto,而可定义多个comparator,java 8后推荐lambda表达式。

当需要对对象进行排序时,Comparable 和 Comparator 是 Java 中最常用的两种方式。选哪个,关键看排序逻辑是否属于对象的“天然属性”——如果该排序规则是类本身固有的、稳定的、普遍认可的(比如 String 按字典序、Integer 按数值大小),优先用 Comparable;如果排序规则多变、临时、或不归类自身管(比如按姓名长度、按创建时间倒序、按多个字段组合),就用 Comparator。
用 Comparable 实现自然排序
实现 Comparable 接口,重写 compareTo() 方法,表示“这个类默认怎么比”。它是一劳永逸的内置约定,所有使用 Collections.sort() 或 Arrays.sort() 的地方都会自动生效。
- 适合定义对象最核心、最通用的比较逻辑(如 Person 默认按 id 升序)
- 一个类只能有一个 compareTo 实现,不能同时支持多种自然序
- 修改 Comparable 会影响所有依赖默认排序的代码,需谨慎
- 注意 null 安全:compareTo 中要主动处理 null 值,否则运行时可能抛 NullPointerException
用 Comparator 实现灵活排序
Comparator 是独立于类的函数式接口,可通过匿名内部类、Lambda 或方法引用快速构建。它把“怎么比”和“谁来比”解耦,特别适合场景化、一次性的、或第三方类无法修改的情况。
- 可为同一类定义多个 Comparator(如按年龄、按姓名、按分数降序)
- 能直接用于 Stream.sorted()、TreeSet/TreeMap 构造、Collections.sort(list, comp)
- 推荐用静态工具方法封装常用 Comparator,例如 Person::comparingAge(),提升复用性
- Java 8 后优先用 Lambda 表达式,简洁清晰:(a, b) -> Integer.compare(a.getScore(), b.getScore())
实际选型建议
先问自己三个问题:
- 这个排序是不是“这个类本来就应该这样排”?如果是 → Comparable
- 是否需要同时支持多种排序方式?是 → 必须用 Comparator
- 要排序的类是 JDK 类或别人写的、你没法改源码?是 → 只能用 Comparator
常见组合策略:类实现 Comparable 定义主键顺序(如 ID),再配合多个静态 Comparator 处理业务维度(如按更新时间、按状态分组)。这样既保持语义清晰,又不失灵活性。










