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

如何对List按年龄分组并统计人数?
该操作通过 Collectors.groupingBy(User::getAge, Collectors.counting()) 实现,返回 Map<integer long></integer>。输入为一组包含年龄字段的 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);
}
}
预期输出:{25=2, 30=2}。验证:25岁有Alice和Charlie共2人,30岁有Bob和Diana共2人。类型正确,无异常。
立即学习“Java免费学习笔记(深入)”;
如何对List按客户ID分组并统计总金额?
该操作通过 Collectors.groupingBy(Order::getCustomerId, Collectors.summingDouble(Order::getAmount)) 实现,返回 Map<string double></string>。输入为包含客户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);
}
}
预期输出:{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的明确行为,无需额外判空处理。


















