怎么用 Comparator 分组
在 Java 里 Comparator 本身不是用来“分组”的,但可以配合分组操作一起使用。常见做法有下面几种,按使用频率从高到低给你讲清楚。
一、最常见:Comparator + Map 分组(强烈推荐)
示例:按某个字段分组
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
}
使用 Collectors.groupingBy
List list = List.of(
new Person("A", 20),
new Person("B", 20),
new Person("C", 30)
);
Map> groupByAge =
list.stream()
.collect(Collectors.groupingBy(Person::getAge));
✅ 结果:
20 -> [A, B]
30 -> [C]
二、分组 + 排序(Comparator 出场)
1️⃣ 分组后,组内排序
Map> result =
list.stream()
.collect(Collectors.groupingBy(
Person::getAge,
Collectors.collectingAndThen(
Collectors.toList(),
l -> {
l.sort(Comparator.comparing(Person::getName));
return l;
}
)
));
三、用 Comparator 自定义“分组键”(进阶)
场景:年龄按区间分组(不是直接用字段)
Map> group =
list.stream()
.collect(Collectors.groupingBy(p -> {
if (p.getAge() < 25) return "青年";
else return "中年";
}));
✅ 结果:
青年 -> [A, B]
中年 -> [C]
四、用 Comparator 做“排序 + 分组效果”(容易混淆)
⚠️ Comparator 只能排序,不能直接分组
list.sort(Comparator.comparing(Person::getAge));
这只是:
[20, 20, 30]
不是分组,只是顺序变了。
五、TreeMap + Comparator(有序分组)
按年龄排序并分组
TreeMap> map =
list.stream()
.collect(Collectors.groupingBy(
Person::getAge,
TreeMap::new,
Collectors.toList()
));
六、总结对照表
| 目的 | 是否用 Comparator | 推荐方式 |
|---|---|---|
| 分组 | ❌ | Collectors.groupingBy |
| 分组 + 排序 | ✅ | groupingBy + Comparator |
| 排序 | ✅ | Comparator |
| 有序分组 | ✅ | TreeMap + groupingBy |
一句话总结 ✅
Comparator 负责“怎么比”,groupingBy 负责“怎么分”
两者通常 配合使用,而不是替代关系
如果你有具体场景(比如:按多个字段分组?按对象某个规则分组?),可以直接贴代码,我帮你写完整示例。