Java stream groupingBy sorted 实现多条件排序与分组的最佳实践
1. 数据初始化
这一部分代码用于创建 Product 对象并将它们添加到 result 列表中。
// 初始化数据
List<Product> result = new ArrayList<>();
List<Product> resp = new ArrayList<>();// 添加产品数据
result.add(new Product("手机A", 1500, "电子", 3, 5));
result.add(new Product("手机B", 1600, "电子", 3, 5));
result.add(new Product("手机C", 1800, "电子", 3, 5));
result.add(new Product("电脑A", 13000, "电子", 3, 6));
result.add(new Product("电脑B", 15000, "电子", 3, 6));
result.add(new Product("电脑C", 18000, "电子", 3, 6));result.add(new Product("床C", 7000, "家具", 1, 4));
result.add(new Product("椅子A", 500, "家具", 1, 3));
result.add(new Product("椅子B", 400, "家具", 1, 3));
result.add(new Product("椅子C", 300, "家具", 1, 3));result.add(new Product("牙膏A", 15, "洗护", 2, 1));
result.add(new Product("牙膏B", 25, "洗护", 2, 1));
result.add(new Product("牙膏C", 18, "洗护", 2, 1));
result.add(new Product("洗面奶A", 60, "洗护", 2, 2));
result.add(new Product("洗面奶B", 70, "洗护", 2, 2));
result.add(new Product("洗面奶C", 80, "洗护", 2, 2));
说明
Product类:表示一个产品对象,包含以下属性:name:产品名称。price:产品价格。type:产品类型(如电子、家具、洗护)。seq0和seq1:排序辅助字段。
result列表:存储所有产品对象。resp列表:用于存储最终输出的结果。
2. 按价格排序并分组
这一部分代码对 result 列表中的产品按价格排序后,按 type 字段分组。
// 按价格排序并分组
Map<String, List<Product>> collect = result.stream().sorted(Comparator.comparing(Product::getPrice)) // 按价格升序排序.collect(Collectors.groupingBy(Product::getType, // 按类型分组LinkedHashMap::new, // 保持分组顺序Collectors.toList() // 分组后每组存为 List));
说明
- 排序:使用
Comparator.comparing(Product::getPrice)对产品按价格升序排序。 - 分组:使用
Collectors.groupingBy按type字段分组。 - 结果:
collect是一个Map,键为产品类型(如 “电子”、“家具”),值为对应类型的产品列表。
3. 对分组后的数据排序
这一部分代码对每个分组内的产品列表进行排序,先按 seq1 正序,再按价格倒序。
// 对分组后的数据按 seq1 正序和价格倒序排序
Map<String, List<Product>> sortedCollect = result.stream().collect(Collectors.groupingBy(Product::getType, // 按类型分组LinkedHashMap::new, // 保持分组顺序Collectors.collectingAndThen(Collectors.toList(), // 先收集到 Listlist -> list.stream().sorted(Comparator.comparing(Product::getPrice).reversed()) // 价格倒序.sorted(Comparator.comparing(Product::getSeq1)) // seq1 正序.collect(Collectors.toList()) // 排序后收集为 List)));
说明
- 分组:与上一步类似,按
type字段分组。 - 排序逻辑:
- 价格倒序:
Comparator.comparing(Product::getPrice).reversed()。 seq1正序:Comparator.comparing(Product::getSeq1)。- 排序优先级:先按
seq1排序,再按价格排序。
- 价格倒序:
- 结果:
sortedCollect是一个Map,每个分组内的产品列表已按上述规则排序。
4. 对分组的键排序
这一部分代码对分组的键(即产品类型)按字典序排序。
// 对分组后的 key 进行排序
Map<String, List<Product>> sortedMap2 = sortedCollect.entrySet().stream().sorted(Map.Entry.comparingByKey()) // 按键(类型)排序.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,(oldVal, newVal) -> oldVal,LinkedHashMap::new // 保持插入顺序));
说明
- 排序逻辑:
Map.Entry.comparingByKey()按键(类型)字典序排序。 - 结果:
sortedMap2是一个按类型排序的Map,每个分组内的产品列表已按规则排序。
5. 按顺序取出每组的第 i 个元素
这一部分代码从每个分组中依次取出第 i 个元素,直到所有元素都被取出。
// 遍历分组数据,按顺序取出每组的第 i 个元素
int index = 0;
boolean done = false;while (!done) {done = true;for (String key : sortedMap2.keySet()) {List<Product> group = sortedMap2.get(key);if (index < group.size()) {String name = sortedMap2.get(key).get(index).name;System.out.println("name: " + name);resp.add(group.get(index)); // 添加到结果列表done = false; // 如果还有未取出的元素,继续循环}}index++;
}
说明
- 逻辑:
- 遍历每个分组,取出第
index个元素。 - 如果某个分组的元素已取完,则跳过。
- 当所有分组的元素都取完时,退出循环。
- 遍历每个分组,取出第
- 结果:
resp列表按顺序存储所有产品。
6. 按每组的第 i 个元素重新排序
这一部分代码实现了另一种遍历方式,按每组的第 i 个元素重新排序。
// 计算每组的最大长度
int count = 0;
for (String key : sortedMap2.keySet()) {count = Math.max(count, sortedMap2.get(key).size());
}// 按每组的第 i 个元素重新排序
int j = 0;
for (int i = 0; i < count; i++) {for (String key : sortedMap2.keySet()) {if (i >= sortedMap2.get(key).size()) {continue; // 跳过超出范围的元素}String name = sortedMap2.get(key).get(i).name;System.out.println("name: " + name);resp.add(j, sortedMap2.get(key).get(i)); // 插入到结果列表j++;}
}
说明
- 逻辑:
- 计算每组的最大长度
count。 - 遍历每组的第
i个元素,按顺序插入到resp列表中。
- 计算每组的最大长度
- 结果:
resp列表存储按每组第i个元素排序的结果。
7. 产品类定义
Product 类是代码的核心数据结构,定义如下:
static class Product {String name;int price;String type;int seq0;int seq1;public Product(String name, int price, String type, int seq0, int seq1) {this.name = name;this.price = price;this.type = type;this.seq0 = seq0;this.seq1 = seq1;}public String getName() {return name;}public int getPrice() {return price;}public String getType() {return type;}public int getSeq0() {return seq0;}public int getSeq1() {return seq1;}
}
总结
通过拆分代码,我们可以清晰地看到每个部分的功能:
- 数据初始化。
- 按价格排序并分组。
- 对分组内的产品排序。
- 对分组的键排序。
- 按顺序取出每组的第
i个元素。 - 按每组的第
i个元素重新排序。
如果需要进一步优化或补充说明,请随时告知!
相关文章:
Java stream groupingBy sorted 实现多条件排序与分组的最佳实践
1. 数据初始化 这一部分代码用于创建 Product 对象并将它们添加到 result 列表中。 // 初始化数据 List<Product> result new ArrayList<>(); List<Product> resp new ArrayList<>();// 添加产品数据 result.add(new Product("手机A", 1…...
JAVA:代理模式(Proxy Pattern)的技术指南
1、简述 代理模式(Proxy Pattern)是一种结构型设计模式,用于为其他对象提供一种代理,以控制对这个对象的访问。通过代理模式,我们可以在不修改目标对象代码的情况下扩展功能,满足特定的需求。 设计模式样例:https://gitee.com/lhdxhl/design-pattern-example.git 2、什…...
爬取Q房二手房房源信息
文章目录 1. 实战概述2. 网站页面分析3. 编写代码爬取Q房二手房房源信息3.1 创建项目与程序3.2 运行程序,查看结果 4. 实战小结 1. 实战概述 本次实战项目旨在通过编写Python爬虫程序,抓取深圳Q房网上的二手房房源信息。我们将分析网页结构,…...
Ansible自动化运维(五) 运维实战
Ansible自动化运维这部分我将会分为五个部分来为大家讲解 (一)介绍、无密钥登录、安装部署、设置主机清单 (二)Ansible 中的 ad-hoc 模式 模块详解(15)个 (三)Playbook 模式详解 …...
K-means算法的python实现
K-means算法步骤 初始化质心:输入初始的质心位置。分配样本:将每个数据点分配到离它最近的质心对应的簇中。更新质心:对每个簇中的所有数据点,计算它们的均值,并将均值更新为新的质心。重复步骤2和3,直到质…...
客户端(浏览器)vue3本地预览txt,doc,docx,pptx,pdf,xlsx,csv,
预览文件 1、入口文件preview/index.vue2、预览txt3、预览doc4、预览pdf5、预览pptx6、预览xlsx7、预览csv 1、入口文件preview/index.vue 预览样式,如pdf 文件目录如图所示: 代码如下 <template><div class"preview-wrap" ref&…...
[SZ901]JTAG高速下载设置(53Mhz)
SZ901最高支持JTAG 53MHz的时钟频率,下载bit文件和固化程序的速度提升非常明显。 首先设置参数 1,将JTAG0 分频系数修改为3 2,设置参数,更新参数。(完成) 打开VIVADO VIVADO 正常识别FPGA,速…...
docker springboot 运维部署详细实例
环境安装 [rootiZbp1dcnzq7pzpg9607m6pZ ~]# docker -v Docker version 26.1.4, build 5650f9b镜像构建 Dockerfile 文件内容 FROM openjdk:8 # Author Info 创建人信息 MAINTAINER ratelcloudfoxmail.com ENV PORT20001 EXPOSE 20001 RUN mkdir /usr/local/ratel-boot-serv…...
Linux 查看目录命令 ls 详细介绍
Linux 和 Unix 系统中 ls 命令是用于列出目录内容。用户可以查看指定目录下的文件和子目录,还可以获取有关这些文件和子目录的详细信息。 基本语法: ls [选项] [目录]如果不指定目录,ls 将列出当前工作目录下的内容。 01、-a 或 --all ls…...
React Native状态管理器Redux、MobX、Context API、useState
Redux、MobX、Context API、useState都是React中用于状态管理的工具,但它们各自有不同的特点和使用场景。 Redux 介绍: Redux是一个JavaScript状态管理库,最初由Dan Abramov和Andrew Clark于2015年开发。它基于Flux架构,强调状态…...
Three.js资源-模型下载网站
在使用 Three.js 进行 3D 开发时,拥有丰富的模型资源库可以大大提升开发效率和作品质量。以下是一些推荐的 Three.js 模型下载网站,它们提供了各种类型的 3D 模型,适合不同项目需求。无论你是需要逼真的建筑模型,还是简单的几何体…...
linux 添加默认网关
在linux 可以使用 route 命令添加默认网关,假设添加的默认网关是192.168.159.2 添加方式如下: route add default gw 192.168.159.2 以上命令只需要把add 改成 del ,就能删除刚才添加的路由 route del default gw 192.168.159.2 #该命…...
【学习笔记】深入浅出详解Pytorch中的View, reshape, unfold,flatten等方法。
文章目录 一、写在前面二、Reshape(一)用法(二)代码展示 三、Unfold(一)torch.unfold 的基本概念(二)torch.unfold 的工作原理(三) 示例代码(四&a…...
CTFHUB-web(SSRF)
内网访问 点击进入环境,输入 http://127.0.0.1/flag.php 伪协议读取文件 /?urlfile:///var/www/html/flag.php 右击查看页面源代码 端口扫描 1.根据题目提示我们知道端口号在8000-9000之间,使用bp抓包并进行爆破 POST请求 点击环境,访问flag.php 查看页…...
分解质因数
给定 n个正整数 ,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。 输入格式 第一行包含整数 n 接下来 n行,每行包含一个正整数 。 输出格式 对于每个正整数 ,按照从小到大的顺序输出其分解质因数后&…...
前景物体提取
参考:精选课:C完整的实现双目摄像头图像采集、双目摄像头畸变矫正、前景物体提取、生成视差图、深度图、PCL点云图 前景物体提取是计算机视觉中的一个重要技术,可以用于视频监控、虚拟现实和计算机视觉等领域。 1.前景物体提取的原理 前景…...
Kotlin复习
一、Kotlin类型 1.整数 2.浮点 显示转换: 所有数字类型都支持转换为其他类型,但是转换前会检测长度。 toByte(): Byte toShort(): Short toInt(): Int toLong(): Long toFloat(): Float toDouble(): Double 不同进制的数字表示方法(为了提高…...
【AI日记】24.12.17 kaggle 比赛 2-6 | 把做饭看成一种游戏 | 咖喱牛肉
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 参加:kaggle 比赛 Regression with an Insurance Dataset时间:9 小时睡得好很重要 读书 书名:富兰克林自传时间:0.5 小时阅读原因:100 美元纸…...
操作系统(14)请求分页
前言 操作系统中的请求分页,也称为页式虚拟存储管理,是建立在基本分页基础上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能的一种内存管理技术。 一、基本概念 分页:将进程的逻辑地址空间分成若干个大小相等的页&am…...
uniapp navigateTo、redirectTo、reLaunch等页面路由跳转方法的区别
uni.switchTab 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 // app.json {"tabBar": {"list": [{"pagePath": "index","text": "首页"},{"pagePath": "other","text&…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
