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&…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
32位寻址与64位寻址
32位寻址与64位寻址 32位寻址是什么? 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元(地址),其核心含义与能力如下: 1. 核心定义 地址位宽:CPU或内存控制器用32位…...
Docker环境下安装 Elasticsearch + IK 分词器 + Pinyin插件 + Kibana(适配7.10.1)
做RAG自己打算使用esmilvus自己开发一个,安装时好像网上没有比较新的安装方法,然后找了个旧的方法对应试试: 🚀 本文将手把手教你在 Docker 环境中部署 Elasticsearch 7.10.1 IK分词器 拼音插件 Kibana,适配中文搜索…...