comparable是类自身定义的默认排序规则,comparator是外部指定的临时排序方式;前者需实现compareto方法且影响所有排序场景,后者通过compare方法支持同一类型多种排序逻辑且不修改原类。

Comparable 是类自己定的默认排序规则,Comparator 是你临时指定的另一种排法。核心不是“能不能排”,而是“谁来定、怎么定、能定几个”。
Comparable:类自己声明“我天生就该这么排”
实现 Comparable 接口,等于在类内部写死一条排序逻辑。比如 String 按字典序、Integer 按数值大小——这是它最合理、最常被用的顺序,不依赖外部干预。
- 必须重写 compareTo(T o) 方法,返回负数、0 或正数,表示小于、等于、大于
- 排序时直接调用 Collections.sort(list) 或 Arrays.sort(arr) 即可生效
- 关键约束:compareTo 结果为 0 时,理想情况下 a.equals(b) 也应为 true;否则放进 TreeSet 或作 TreeMap 的 key 可能丢数据或行为异常
- 常见坑:用 age - other.age 做减法可能整数溢出;字符串比较没判空导致 NullPointerException
Comparator:别人帮你定“这次想换个方式排”
它完全独立于目标类,不改一行原代码,就能为同一类定义多种排序方式。比如 Person 类,可以按年龄、按姓名长度、按拼音首字母分别排序,互不影响。
- 重写 compare(T o1, T o2) 方法,语义和 compareTo 一致
- 排序时必须显式传入:Collections.sort(list, comparator) 或 Arrays.sort(arr, comparator)
- Java 8 后推荐用 Lambda 表达式:(p1, p2) -> Integer.compare(p1.getAge(), p2.getAge()),避免减法溢出
- 适用场景:第三方类没实现 Comparable、同一类需多套业务排序、测试时临时切换逻辑
怎么选?看需求是否需要“不止一种排法”
如果这个类只有一种公认合理的默认顺序(比如时间戳越小越早、金额越小越低),就实现 Comparable;如果排序规则会变、要支持多种维度、或者类你根本改不了,那就用 Comparator。
- 只传集合/数组进 sort:要求元素类型已实现 Comparable,否则运行时报 ClassCastException
- 多传一个 Comparator 参数:不管类有没有 Comparable,都按你给的规则排
- 注意副作用:Collections.sort() 直接修改原 List;Stream.sorted().collect() 生成新集合,性能开销大,非必要不用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











