如何根据对象字段对列表进行分组并生成嵌套列表
发布时间 - 2026-01-31 00:00:00 点击率:次本文介绍如何基于 java 8 stream api 和 collectors.groupingby,按对象的指定字段(如 shape、size 或二者组合)将 list>,适用于多策略分组场景。
在实际开发中,常需根据业务类型(如 "type_1"、"type_2")对同一对象列表执行不同维度的分组逻辑:仅按 shape、仅按 size,或联合按 shape 和 size。核心目标是将原始 List> —— 即每个子列表包含字段值相同的对象。
✅ 基础分组:按单个字段(如 shape)
使用 Collectors.groupingBy(Obj::getShape) 可将对象按 shape 分组为 Map
public List> groupByShape(List
objs) { return new ArrayList<>(objs.stream() .collect(Collectors.groupingBy(Obj::getShape)) .values()); }
⚠️ 注意:请确保 Obj 类已提供 getShape()(及 getSize())等标准 getter 方法;若字段为 private,直接访问 obj.shape 在 lambda 中不可行。
✅ 进阶分组:按多个字段(如 shape + size)
联合分组需构造唯一键。推荐使用 AbstractMap.SimpleEntry 或自定义键类,但最简洁安全的方式是用 Record(Java 14+)或匿名对象(Java 17+),或拼接字符串(需确保无歧义):
// 方式1:使用 record(推荐,类型安全、可读性高) public List> groupByShapeAndSize(List
objs) { return new ArrayList<>(objs.stream() .collect(Collectors.groupingBy( obj -> new AbstractMap.SimpleImmutableEntry<>(obj.getShape(), obj.getSize()) )) .values()); } // 方式2:字符串拼接(兼容低版本,但需注意转义,如 shape="a_b", size="c_d" 可能冲突) public List > groupByShapeAndSizeSafe(List
objs) { return new ArrayList<>(objs.stream() .collect(Collectors.groupingBy( obj -> obj.getShape() + "\0" + obj.getSize() // 使用不可见分隔符 \0 更安全 )) .values()); }
✅ 统一调度:在 functionName 中集成策略
将分组逻辑封装为函数式接口,使主流程清晰可维护:
public void functionName(Map> objMap) { Map , List >>> strategies = Map.of( "type_1", this::groupByShape, "type_2", this::groupBySize, "type_3", this::groupByShapeAndSize ); objMap.forEach((type, objs) -> { Function
, List
>> strategy = strategies.get(type); if (strategy != null) { List
> grouped = strategy.apply(objs); // ✅ 此处执行后续处理:如统计、聚合、持久化等 processGroupedResults(grouped); } }); } private void processGroupedResults(List
> grouped) { for (int i = 0; i < grouped.size(); i++) { System.out.println("Group " + (i + 1) + ": " + grouped.get(i).size() + " objects"); // e.g., grouped.get(i) is a List
with same shape/size } }
? 验证示例输出
以输入:
{
"key": "type_3",
"value": [
{"size":"m1","shape":"s1","name":"Obj_1"},
{"size":"m2","shape":"s1","name":"Obj_2"},
{"size":"m1","shape":"s1","name":"Obj_3"}
]
}调用 groupByShapeAndSize() 后,将生成:
- [(s1,m1) → [Obj_1, Obj_3]]
- [(s1,m2) → [Obj_2]]
→ 最终 List- > 包含两个子列表,完全符合预期。
✅ 总结
- 使用 Collectors.groupingBy 是实现动态分组的最简高效方案;
- 单字段分组直接传方法引用(如 Obj::getShape);
- 多字段分组优先使用 SimpleImmutableEntry 或 record 构建复合键,避免字符串拼接风险;
- 将分组策略与主逻辑解耦(如 Map
),提升可扩展性与可测试性; - 所有分组结果均为内存内 List
- >,无需额外依赖,开箱即用。
# java
# js
# app
# stream
# String
# 封装
# 字符串
# Lambda
# 接口
# private
# map
# function
# 对象
# 多字
# 进阶
# 多个
# 推荐使用
# 均为
# 适用于
# 自定义
# 可将
# 转换为
# 中不
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】
音响网站制作视频教程,隆霸音响官方网站?
高性价比服务器租赁——企业级配置与24小时运维服务
什么是JavaScript解构赋值_解构赋值有哪些实用技巧
车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?
作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】
Laravel如何处理异常和错误?(Handler示例)
Claude怎样写约束型提示词_Claude约束提示词写法【教程】
C++时间戳转换成日期时间的步骤和示例代码
javascript如何操作浏览器历史记录_怎样实现无刷新导航
深圳网站制作培训,深圳哪些招聘网站比较好?
Bootstrap CSS布局之列表
在Oracle关闭情况下如何修改spfile的参数
Javascript中的事件循环是如何工作的_如何利用Javascript事件循环优化异步代码?
利用python获取某年中每个月的第一天和最后一天
php做exe能调用系统命令吗_执行cmd指令实现方式【详解】
标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?
如何有效防御Web建站篡改攻击?
百度浏览器网页无法复制文字怎么办 百度浏览器复制修复
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
如何快速打造个性化非模板自助建站?
香港服务器租用费用高吗?如何避免常见误区?
Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧
Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】
大连 网站制作,大连天途有线官网?
Laravel怎么在Controller之外的地方验证数据
Python面向对象测试方法_mock解析【教程】
Laravel API资源(Resource)怎么用_格式化Laravel API响应的最佳实践
浅述节点的创建及常见功能的实现
美食网站链接制作教程视频,哪个教做美食的网站比较专业点?
C语言设计一个闪闪的圣诞树
5种Android数据存储方式汇总
原生JS实现图片轮播切换效果
Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】
佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】
Laravel Eloquent:优雅地将关联模型字段扁平化到主模型中
如何快速生成ASP一键建站模板并优化安全性?
米侠浏览器网页图片不显示怎么办 米侠图片加载修复
javascript事件捕获机制【深入分析IE和DOM中的事件模型】
Laravel如何记录日志_Laravel Logging系统配置与自定义日志通道
网站建设保证美观性,需要考虑的几点问题!
Laravel项目如何进行性能优化_Laravel应用性能分析与优化技巧大全
Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)
java获取注册ip实例
Android滚轮选择时间控件使用详解
Zeus浏览器网页版官网入口 宙斯浏览器官网在线通道
如何快速辨别茅台真假?关键步骤解析
打造顶配客厅影院,这份100寸电视推荐名单请查收
南京网站制作费用,南京远驱官方网站?
DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解


