Java8 Comparator接口 和 List Steam 排序使用案例
在Java中,Comparator接口主要用于实现自定义排序逻辑,适用于未实现Comparable接口或需要覆盖默认比较规则的场景。以下是核心使用方法和注意事项:
一、基础用法
匿名内部类实现
传统方式通过匿名内部类重写compare()
方法,例如对整数降序排序:List<Integer> list = Arrays.asList(3, 1, 2); list.sort(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) {// 降序 return o2 - o1; } } );
此方式在Java 8之前常见。
Lambda表达式简化
Java 8后可用Lambda替代匿名类,代码更简洁:list.sort((o1, o2) -> o2 - o1);
或使用方法引用:
list.sort(Comparator.reverseOrder());
适用于简单排序场景。
二、高级特性
多条件排序
使用thenComparing()
实现多级排序,例如先按年龄升序,再按姓名降序:List<Person> people = ...; people.sort( Comparator.comparing(Person::getAge) .thenComparing(Comparator.comparing(Person::getName).reversed() ) );
支持链式调用,灵活组合排序规则。
处理null值
需显式处理null避免NullPointerException
,例如将null排在末尾:list.sort((a, b) -> {if (a == null) return 1;if (b == null) return -1; return a.compareTo(b);});
注意违反自反性会导致
Comparison method violates its general contract
错误。
三、Comparator与Comparable对比
维度 | Comparator | Comparable |
---|---|---|
实现位置 | 独立类或匿名类 | 目标类内部实现 |
排序规则 | 支持多种自定义规则 | 仅提供单一自然排序 |
侵入性 | 无侵入,不影响原有类 | 需修改类结构 |
典型应用场景 | 第三方类排序、多规则排序 | 类自身有明确排序逻辑(如String) |
优先使用Comparator实现灵活排序,尤其是需要动态调整规则时。
四、常见问题
- 整数溢出风险
避免直接返回o1 - o2
,应使用Integer.compare(o1, o2)。
- JDK8增强方法
Comparator.naturalOrder()
:自然排序Comparator.nullsFirst()
:将null置于开头Comparator.comparingInt()
:避免装箱开销68。
通过合理应用Comparator,可高效实现复杂排序需求,同时保持代码可维护性。
Java 8的 Stream API 提供了强大的List排序功能,主要通过sorted()
方法实现,支持自然排序、自定义排序以及多条件组合排序。以下是核心用法总结:
1. 基础排序
- 自然排序(升序):直接调用
sorted()
方法,元素需实现Comparable
接口list.stream().sorted().collect(Collectors.toList());
- 降序排序:通过
Comparator.reverseOrder()
或reversed()
方法list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());// 或 list.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());
2. 自定义排序
- 单字段排序:使用
Comparator.comparing()
指定字段list.stream().sorted(Comparator.comparing(Student::getScore)).collect(Collectors.toList());
- 多字段排序:通过
thenComparing()
链式调用list.stream() .sorted(Comparator.comparing(Student::getAge) .thenComparing(Student::getName)) .collect(Collectors.toList());
3. 空值处理
- 空值优先/后置:使用
Comparator.nullsFirst()
或Comparator.nullsLast()
list.stream() .sorted(Comparator.comparing(Student::getAge, Comparator.nullsFirst(Integer::compareTo))) .collect(Collectors.toList());
4. 性能提示
sorted()
操作对大型流可能较昂贵,若数据已排序可跳过此操作2- 复杂排序建议预编译
Comparator
以减少重复计算9
完整示例:
List<Student> students = Arrays.asList( new Student("Alice", 25), new Student("Bob", 20) );List<Student> sorted = students.stream() .sorted(Comparator.comparing(Student::getAge).reversed()) .collect(Collectors.toList());