JDK 1.8下使用Comparator按多条件排序Person集合的方法
这个需求用Java 8的Comparator API可以轻松搞定,核心就是把你的排序规则拆成多级优先级,然后用Comparator的链式调用组合起来就行,咱们一步步来:
先明确排序规则的优先级
咱们把规则拆解成两层优先级:
- 第一优先级:所有
favorite=true的Person必须排在最前面,不管count值是正、负还是0; - 第二优先级:在
favorite=false的元素里,count>0的排在count==0的前面(如果有count<0的情况,按规则字面意思会归到最后一组,要是需要单独处理可以调整)。
实现Comparator的核心逻辑
Java 8的Comparator提供了comparingInt、thenComparing这些静态方法,能让我们用简洁的方式实现多级排序:
1. 第一优先级比较器
我们需要让favorite=true的元素排在前面,最简单的方式是把布尔值转换成整数:true对应0,false对应1(数字越小排得越靠前)。代码如下:
Comparator.comparingInt((Person p) -> p.favorite ? 0 : 1)
当然你也可以用Comparator.comparing(Person::isFavorite).reversed(),因为Boolean的默认排序是false在前,反转后true就跑到前面了,不过用整数映射的方式更直观,尤其是后面要扩展规则的时候。
2. 第二优先级比较器
同样用整数映射的思路,把count>0的元素映射为0,count==0的映射为1:
Comparator.comparingInt(p -> p.count > 0 ? 0 : 1)
3. 链式组合两个比较器
用thenComparing把两个比较器串起来,这样会先按第一优先级排序,当第一优先级相同(即favorite值一样)时,再按第二优先级排序:
Comparator<Person> personComparator = Comparator.comparingInt((Person p) -> p.favorite ? 0 : 1) .thenComparingInt(p -> p.count > 0 ? 0 : 1);
完整代码示例
下面是包含测试的完整代码,你可以直接运行看效果:
import java.util.ArrayList; import java.util.Comparator; import java.util.List; class Person { public String name; public int count; public boolean favorite; // 构造函数方便创建测试对象 public Person(String name, int count, boolean favorite) { this.name = name; this.count = count; this.favorite = favorite; } // 重写toString方便打印结果 @Override public String toString() { return "Person{name='" + name + "', count=" + count + ", favorite=" + favorite + "}"; } } public class PersonSortDemo { public static void main(String[] args) { // 创建覆盖所有情况的测试数据 List<Person> people = new ArrayList<>(); people.add(new Person("Alice", 0, false)); people.add(new Person("Bob", 5, false)); people.add(new Person("Charlie", 0, true)); people.add(new Person("Dave", 10, true)); people.add(new Person("Eve", -3, true)); // 测试count为负的情况,因为favorite=true,依然排在前面 people.add(new Person("Frank", 0, false)); // 应用排序逻辑 people.sort(Comparator.comparingInt((Person p) -> p.favorite ? 0 : 1) .thenComparingInt(p -> p.count > 0 ? 0 : 1)); // 打印排序后的结果 people.forEach(System.out::println); } }
预期输出结果
运行上面的代码,你会看到输出按规则排列:
Person{name='Charlie', count=0, favorite=true} Person{name='Dave', count=10, favorite=true} Person{name='Eve', count=-3, favorite=true} Person{name='Bob', count=5, favorite=false} Person{name='Alice', count=0, favorite=false} Person{name='Frank', count=0, favorite=false}
所有favorite=true的元素排在最前面,然后是favorite=false且count>0的Bob,最后是favorite=false且count=0的Alice和Frank。
扩展说明
如果你的规则需要区分count<0的情况(比如把count<0的放在count==0的后面),只需要调整第二优先级的映射逻辑就行:
.thenComparingInt(p -> p.count > 0 ? 0 : (p.count == 0 ? 1 : 2))
这样count>0的排第一,count==0的排第二,count<0的排最后。
内容的提问来源于stack exchange,提问作者Kapparino

