Java中Lambda配合Stream API分组统计的核心是Collectors.groupingBy(),支持按单字段分组、计数、数值聚合(求和/平均/最值)及多级分组,语法简洁、逻辑清晰。

Java 中 Lambda 表达式配合 Stream API 做分组统计,核心就是 Collectors.groupingBy() —— 它能把一个流按某个属性或规则“切”成若干组,再对每组做计数、求和、平均、聚合等操作。写法简洁,逻辑清晰,比手写 for 循环 + Map + if 判断干净太多。
按单个字段分组并获取每组列表
最基础的用法:把元素按某属性归类,返回 `Map
>`
比如按部门分组员工:
```java
Map> byDept = people.stream()
.collect(Collectors.groupingBy(Person::getDepartment));
```
结果形如:`{"IT"=[p1,p3], "HR"=[p2,p4]}`
注意:key 是 `getDepartment()` 返回值(String),value 是该部门所有 Person 对象的 List。
分组后直接统计数量(不用存整个列表)
如果只关心“每组有多少人”,用 `Collectors.counting()` 作为下游收集器:
```java
Map deptCount = people.stream()
.collect(Collectors.groupingBy(Person::getDepartment, Collectors.counting()));
```
结果是 `{"IT"=2, "HR"=3}` —— 类型是 `Long`,不是 `Integer`,因为 `counting()` 返回的是 `long`。
分组 + 数值聚合(求和、平均、最值)
常见需求:每个部门的年龄总和、平均年龄、最大年龄的人
- 求和:
```java
Map sumAge = people.stream()
.collect(Collectors.groupingBy(Person::getDepartment, Collectors.summingInt(Person::getAge)));
```
- 平均:
```java
Map avgAge = people.stream()
.collect(Collectors.groupingBy(Person::getDepartment, Collectors.averagingDouble(Person::getAge)));
```
- 最大年龄的员工(返回 `Optional`):
```java
Map> maxPerson = people.stream()
.collect(Collectors.groupingBy(Person::getDepartment,
Collectors.maxBy(Comparator.comparing(Person::getAge))));
```
取值时记得判空:`maxPerson.get("IT").orElse(null)`。
多级分组(先按A,再按B)
比如先按性别分,再在每个性别里按年龄段分:
```java
Map>> grouped = people.stream()
.collect(Collectors.groupingBy(
Person::getGender,
Collectors.groupingBy(p -> p.getAge() 不复杂但容易忽略