使用Collectors.groupingBy按地理位置统计业务分布,核心在于合理建模地理字段、明确分组粒度、规范处理空值与地域映射;推荐采用GB/T 2260行政区划代码,优先使用province/city/regionCode等标准字段,避免模糊描述,并通过预处理统一港澳台等别名,确保报表准确可对齐。

用 Collectors.groupingBy 按地理位置统计全国业务分布,核心是把“地区字段”作为分组键,再结合下游收集器(如计数、求和、聚合对象)生成结构化报表。关键不在 groupingBy 本身,而在数据建模是否合理、地区层级是否清晰、空值与归类逻辑是否处理得当。
明确地理维度字段与分组粒度
业务数据中需有可稳定标识地理位置的字段,例如:province(省份)、city(地级市)、regionCode(标准行政区划代码)。避免使用模糊字段(如“华东区”“总部附近”),否则分组结果不可靠。
- 若要按省汇总,直接以
Business::getProvince为分类函数 - 若需省+市两级嵌套,可用
groupingBy(b -> b.getProvince(), groupingBy(b -> b.getCity())) - 推荐使用国家统计局最新《行政区划代码》(GB/T 2260)中的 6 位 code,便于标准化合并(如前两位代表省,可截取做省级分组)
基础计数报表:统计各地区业务单量
最常用场景是看每个省有多少条业务记录:
Map<String, Long> provinceCount = businessList.stream()
.collect(Collectors.groupingBy(
Business::getProvince,
Collectors.counting()
));
注意:若 getProvince() 可能返回 null,默认会将 null 作为 key 存入 map,建议提前过滤或用 Objects.toString(b.getProvince(), "未知地区") 统一兜底。
增强型聚合:同时统计数量、金额、平均单额
用 Collectors.collectingAndThen 或自定义下游收集器,避免多次遍历:
Map<String, Summary> provinceSummary = businessList.stream()
.collect(Collectors.groupingBy(
Business::getProvince,
Collectors.collectingAndThen(
Collectors.summarizingDouble(Business::getAmount),
summary -> new Summary(
(long) summary.getCount(),
summary.getSum(),
summary.getAverage()
)
)
));
其中 Summary 是你定义的简单 DTO,封装数量、总额、均值等指标,比单纯返回 DoubleSummaryStatistics 更易序列化和展示。
处理特殊区域与数据对齐
实际业务中常遇到港澳台、海外、未填写、多地址等情况,不能依赖 groupingBy 默认行为:
- 将“香港”“Hong Kong”“HK”等统一映射为“香港特别行政区”,可在分组前用 Map 做标准化预处理
- 对无省市信息的记录,归入“其他”或“待完善”,不丢弃也不混入默认 null 分组
- 如需与政府公开地理数据对齐(如 ECharts 地图组件),确保 key 使用标准名称(如“内蒙古自治区”而非“内蒙”)
不复杂但容易忽略的是数据一致性——groupingBy 只是工具,真正决定报表质量的是原始字段的规范性、空值策略和地域映射逻辑。写完分组代码后,务必用真实样本验证各省 key 是否全覆盖、有无意外空组、金额类指标是否单位统一。

















