在Java集合数据处理场景中,Stream API的groupingBy方法提供了便捷的分组能力,但默认的分组逻辑是固定的。当业务需要根据不同的枚举值动态切换聚合策略时,我们可以通过枚举封装聚合逻辑,结合groupingBy的下游收集器参数实现灵活的动态选择。

基础的分组聚合实现
首先我们来看最基础的groupingBy用法,比如对一个用户列表按照部门分组,统计每个部门的用户数量:
import java.util.*;
import java.util.stream.Collectors;
class User {
private String name;
private String department;
private Integer age;
public User(String name, String department, Integer age) {
this.name = name;
this.department = department;
this.age = age;
}
public String getDepartment() {
return department;
}
public Integer getAge() {
return age;
}
}
public class GroupingByDemo {
public static void main(String[] args) {
List<User> userList = Arrays.asList(
new User("张三", "技术部", 25),
new User("李四", "技术部", 28),
new User("王五", "产品部", 24),
new User("赵六", "产品部", 30)
);
// 基础分组统计每个部门用户数
Map<String, Long> deptCount = userList.stream()
.collect(Collectors.groupingBy(User::getDepartment, Collectors.counting()));
System.out.println(deptCount);
}
}
枚举封装聚合策略
当聚合策略需要动态切换时,我们可以定义一个枚举来封装不同的聚合逻辑,每个枚举实例对应一种特定的聚合方式:
import java.util.*;
import java.util.stream.Collectors;
import java.util.function.Function;
// 聚合策略枚举
enum AggregateStrategy {
// 统计数量
COUNT {
@Override
public <T> Collector<T, ?, Long> getCollector() {
return Collectors.counting();
}
},
// 求和年龄
SUM_AGE {
@Override
public <T> Collector<T, ?, Integer> getCollector() {
return Collectors.summingInt(t -> ((User) t).getAge());
}
},
// 求平均年龄
AVG_AGE {
@Override
public <T> Collector<T, ?, Double> getCollector() {
return Collectors.averagingInt(t -> ((User) t).getAge());
}
};
// 定义获取收集器的抽象方法
public abstract <T> Collector<T, ?, ?> getCollector();
}
动态选择聚合策略的groupingBy实现
接下来我们可以根据传入的枚举值,动态选择对应的聚合策略,完成groupingBy操作:
import java.util.*;
import java.util.stream.Collectors;
public class DynamicGroupingByDemo {
public static void main(String[] args) {
List<User> userList = Arrays.asList(
new User("张三", "技术部", 25),
new User("李四", "技术部", 28),
new User("王五", "产品部", 24),
new User("赵六", "产品部", 30)
);
// 动态选择聚合策略为统计数量
AggregateStrategy strategy1 = AggregateStrategy.COUNT;
Map<String, Long> countResult = groupByWithStrategy(userList, User::getDepartment, strategy1);
System.out.println("统计数量结果:" + countResult);
// 动态选择聚合策略为求和年龄
AggregateStrategy strategy2 = AggregateStrategy.SUM_AGE;
Map<String, Integer> sumResult = groupByWithStrategy(userList, User::getDepartment, strategy2);
System.out.println("年龄求和结果:" + sumResult);
// 动态选择聚合策略为求平均年龄
AggregateStrategy strategy3 = AggregateStrategy.AVG_AGE;
Map<String, Double> avgResult = groupByWithStrategy(userList, User::getDepartment, strategy3);
System.out.println("平均年龄结果:" + avgResult);
}
// 通用动态分组聚合方法
private static <T, K, V> Map<K, V> groupByWithStrategy(
List<T> dataList,
Function<T, K> classifier,
AggregateStrategy strategy
) {
@SuppressWarnings("unchecked")
Collector<T, ?, V> collector = (Collector<T, ?, V>) strategy.getCollector();
return dataList.stream()
.collect(Collectors.groupingBy(classifier, collector));
}
}
方案优势说明
这种实现方式的核心优势在于:
- 聚合逻辑与业务代码解耦,新增聚合策略只需要扩展枚举实例,不需要修改原有业务逻辑
- 动态选择能力灵活,只需要传入不同的枚举值就能切换聚合规则,适配多变的业务需求
- 复用性高,通用的
groupByWithStrategy方法可以适配不同的分组维度和聚合策略组合
如果后续需要新增比如最大年龄、最小年龄等聚合策略,只需要在AggregateStrategy枚举中新增对应的实例,实现getCollector方法即可,不需要改动其他代码。
Java枚举类型groupingBy聚合策略修改时间:2026-06-11 05:06:20