在Java里如何对集合进行分组_Java集合分组操作解析

冬萱大大_6320

冬萱大大_6320

2026-02-04

376人浏览

原创

Collectors.groupingBy()是Java 8 Stream API中实现集合分组的核心方法,接收分类函数返回Map;支持下游收集器定制聚合结果,可嵌套实现多级分组,但需注意null值处理与并发安全限制。

在java里如何对集合进行分组_java集合分组操作解析

用 Collectors.groupingBy() 实现基础分组

Java 8 引入的 Stream API 提供了最常用、最直观的集合分组方式。核心是 Collectors.groupingBy(),它接收一个分类函数(Function),返回 Map>。

比如对 List 按年龄分组:

Map<integer list>> byAge = people.stream()
    .collect(Collectors.groupingBy(Person::getAge));</integer>

注意:键类型必须与分类函数返回值一致;若某对象分类函数返回 null,会抛出 NullPointerException —— 这是常见踩坑点,建议提前判空或用 Collectors.groupingBy(person -> person.getAge() != null ? person.getAge() : -1) 容错。

分组后聚合值不是 List?用下游收集器定制

groupingBy() 默认用 Collectors.toList() 收集元素,但实际常需其他形式:统计数量、求和、取平均、转 Set 等。这时要传入第二个参数 —— 下游收集器(downstream collector)。

  • 统计每组人数:Collectors.groupingBy(Person::getGender, Collectors.counting()) → Map
  • 按城市分组并求平均年龄:Collectors.groupingBy(Person::getCity, Collectors.averagingInt(Person::getAge))
  • 去重分组(避免同名重复):Collectors.groupingBy(Person::getDepartment, Collectors.toSet())

下游收集器决定了最终 value 的类型和语义,选错会导致编译失败或逻辑错误 —— 比如误用 toSet() 却没重写 equals/hashCode,导致分组结果异常。

多级分组:嵌套 groupingBy 或用 groupingByConcurrent?

两层分组(如先按部门、再按职级)可嵌套调用:

Java Api Extractor
Java Api Extractor

从 Java 项目中提取 Controller 层接口定义为 JSON 数据。

下载
Map<string map list>>> grouped = people.stream()
    .collect(Collectors.groupingBy(Person::getDept,
        Collectors.groupingBy(Person::getLevel)));</string>

这种写法清晰,但注意:内层 map 默认是 HashMap,不保证顺序;如需有序,可显式指定 TreeMap::new 作为 mapFactory 参数。

并发场景下,别直接用 groupingByConcurrent() 替换 —— 它只适用于 key 不冲突、且下游收集器线程安全的情况(如 counting()),对 toList() 这类非线程安全收集器,仍可能出错。真正高并发 + 复杂下游时,应考虑分段处理或 parallelStream() 配合手动同步。

原始集合含 null 元素或分组字段为 null 怎么办

groupingBy 对 null 值零容忍:源集合含 null 会触发 NullPointerException;分类函数返回 null 同样崩溃。

稳妥做法是预过滤或映射:

  • 过滤掉空对象:people.stream().filter(Objects::nonNull).collect(...)
  • 对字段为空做兜底:Collectors.groupingBy(p -> p.getCategory() != null ? p.getCategory() : "UNKNOWN")
  • 用 Collectors.groupingBy(keyMapper, LinkedHashMap::new, downstream) 保持插入顺序,同时规避 null 键问题(因 LinkedHashMap 本身允许 null 键,但 groupingBy 仍会拒绝 —— 所以关键还是前端处理)

最容易被忽略的是:数据库查出的实体中,某些字段为 NULL,映射到 Java 对象后变成 null,而业务代码没做任何判空,直接进分组流 —— 这类 NPE 在测试环境常被遗漏,上线后突发。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

6799

3

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1698

6

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

4458

6

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

2025.09.05

650

5

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

2025.11.16

343

7

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.17

533

20

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

2025.11.27

303

6

function是什么
function是什么

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果。本专题为大家提供function是什么的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.04

3320

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习