0

0

如何在Java中将集合元素按照特定规则分组_Stream.groupingBy

P粉602998670

P粉602998670

发布时间:2026-03-05 12:37:10

|

591人浏览过

|

来源于php中文网

原创

默认返回hashmap,不保证顺序;需有序用linkedhashmap::new;多字段分组推荐record组合键;统计数量用counting();key为null直接抛npe,须提前处理。

如何在java中将集合元素按照特定规则分组_stream.groupingby

groupingBy 分组结果是 HashMap 还是 LinkedHashMap?

默认情况下 Collectors.groupingBy() 返回的是 HashMap,不保证插入顺序。如果你依赖分组后的键顺序(比如按原始集合中首次出现顺序),必须显式指定下游收集器:Collectors.groupingBy(keyMapper, LinkedHashMap::new, downstream)

常见错误现象:分组后遍历 Map,发现键的顺序和输入元素出现顺序不一致,误以为逻辑出错。

  • 不指定 map 工厂时,JDK 8+ 默认用 HashMap::new,无序
  • 需要有序请用 LinkedHashMap::new,但注意它不支持并发
  • 若需线程安全且有序,得换方案(如先分组再排序,或用 ConcurrentSkipListMap 配合自定义比较器)

怎么按多个字段分组?

groupingBy 本身只接受一个 Function 作为分类函数,但你可以把多个字段“合成”一个键——最常用的是构造一个不可变的组合对象或用 AbstractMap.SimpleImmutableEntry,更轻量的是拼接字符串(仅限简单场景)。

使用场景:订单列表按 statusregion 联合分组。

立即学习Java免费学习笔记(深入)”;

Spacely AI
Spacely AI

为您的房间提供AI室内设计解决方案,寻找无限的创意

下载
  • 推荐方式:用 record(JDK 14+)或自定义不可变类,例如 record StatusRegion(String status, String region) {},然后 groupingBy(o -> new StatusRegion(o.getStatus(), o.getRegion()))
  • 避免用字符串拼接(如 o.getStatus() + "|" + o.getRegion()),一旦字段含 | 就崩
  • 不要在 key 中放可变对象(如普通 ArrayList),会导致哈希码变化、查找失败

分组后想统计数量而不是收集元素,该用哪个重载?

别写 groupingBy(keyMapper, counting()) ——这会返回 Map<k long></k>,但很多人误以为要手动调 list.size()。其实 counting() 就是为此设计的下游收集器,性能比 mapping(..., toList()) + size() 好得多。

性能影响:对百万级数据,counting() 是单次遍历 O(n),而先收集再取 size 是 O(n) + 内存开销,还可能触发 GC。

  • 正确写法:Map<string long> countByType = list.stream().collect(Collectors.groupingBy(Item::getType, Collectors.counting()));</string>
  • 错误写法:groupingBy(Item::getType, mapping(Function.identity(), toList())) 然后循环取 .size(),纯属浪费内存和 CPU
  • 如果还要同时做其他聚合(如求和、平均值),直接换用 summarizingIntteeing(JDK 12+)

空指针异常(NullPointerException)从哪来?

最常发生在分类函数返回 null 时:groupingBy(obj -> obj.getCategory()),而某个 objgetCategory() 返回 null。此时 Collectors.groupingBy 会直接抛 NullPointerException,不是 NullPointerException 在你代码里,而是在 Collector 内部。

容易踩的坑:以为 null 值会被归到一个叫 "null" 的组里,实际不会——它根本过不了哈希计算那关。

  • 修复方法一:提前过滤,stream.filter(Objects::nonNull).filter(o -> o.getCategory() != null)
  • 修复方法二:在 keyMapper 中兜底,o -> Optional.ofNullable(o.getCategory()).orElse("UNKNOWN")
  • 修复方法三:用 groupingByConcurrent 不会改善这点,null 问题一样存在

真正复杂的地方在于:这个 null 可能来自嵌套调用(比如 user.getAddress().getCity()),堆栈信息不直观,得一层层查源头。别急着加 try-catch,先确认 key 函数是否可能返回 null。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

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

930

2023.08.02

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

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

252

2023.09.22

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

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

1008

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

718

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

219

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1561

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

646

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1148

2024.03.22

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

4

2026.03.05

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.1万人学习

C# 教程
C# 教程

共94课时 | 10.7万人学习

Java 教程
Java 教程

共578课时 | 77万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号