java中实现分组统计的核心做法是调用 collectors.groupingby() 配合下游收集器,将数据源按指定键分组并聚合。具体而言,使用 collectors.summingint() 或 collectors.counting() 作为二级参数,即可在遍历一次数据后直接得到以键为索引、统计值为值的 map。若需处理空值或复杂对象,可结合 collectors.tomap() 手动合并逻辑,但标准流式api已覆盖绝大多数场景。

如何对List按年龄分组并统计人数?
该操作通过 Collectors.groupingBy(User::getAge, Collectors.counting()) 实现,返回 Map。输入为一组包含年龄字段的 User 对象列表,输出为每个年龄段对应的人数映射表。此方法利用Stream API的并行处理能力,无需显式循环即可完成分组与计数。

import java.util.*;
import java.util.stream.Collectors;
class User {
String name;
int age;
User(String n, int a) { name = n; age = a; }
}
public class Main {
public static void main(String[] args) {
List<user> users = Arrays.asList(
new User("Alice", 25),
new User("Bob", 30),
new User("Charlie", 25),
new User("Diana", 30)
);
Map<integer long> result = users.stream()
.collect(Collectors.groupingBy(User::getAge, Collectors.counting()));
System.out.println(result);
}
}</integer></user>
预期输出:{25=2, 30=2}。验证:25岁有Alice和Charlie共2人,30岁有Bob和Diana共2人。类型正确,无异常。
如何对List按客户ID分组并统计总金额?
该操作通过 Collectors.groupingBy(Order::getCustomerId, Collectors.summingDouble(Order::getAmount)) 实现,返回 Map。输入为包含客户ID和金额字段的订单列表,输出为每个客户的消费总额。此方式避免手动初始化Map和累加逻辑,代码更简洁且不易出错。

import java.util.*;
import java.util.stream.Collectors;
class Order {
String customerId;
double amount;
Order(String c, double a) { customerId = c; amount = a; }
}
public class Main {
public static void main(String[] args) {
List<order> orders = Arrays.asList(
new Order("C001", 100.0),
new Order("C002", 200.0),
new Order("C001", 50.0),
new Order("C002", 150.0)
);
Map<string double> result = orders.stream()
.collect(Collectors.groupingBy(Order::getCustomerId, Collectors.summingDouble(Order::getAmount)));
System.out.println(result);
}
}</string></order>
预期输出:{C001=150.0, C002=350.0}。验证:C001订单金额为100+50=150,C002为200+150=350。结果准确,类型匹配。
当分组键为null时,groupingBy如何处理?
Collectors.groupingBy() 允许分组键为null,此时null键会作为一个独立条目存入结果Map中。例如,若输入列表中存在age为null的User对象,则结果Map中将包含一个key为null、value为对应统计值的条目。这是Java 8+ Stream API的明确行为,无需额外判空处理。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











