当前位置: 首页 > news >正文

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:产品类型(如电子、家具、洗护)。
    • seq0seq1:排序辅助字段。
  • 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.groupingBytype 字段分组。
  • 结果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 字段分组。
  • 排序逻辑
    1. 价格倒序Comparator.comparing(Product::getPrice).reversed()
    2. seq1 正序Comparator.comparing(Product::getSeq1)
    3. 排序优先级:先按 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++;
}
说明
  • 逻辑
    1. 遍历每个分组,取出第 index 个元素。
    2. 如果某个分组的元素已取完,则跳过。
    3. 当所有分组的元素都取完时,退出循环。
  • 结果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++;}
}
说明
  • 逻辑
    1. 计算每组的最大长度 count
    2. 遍历每组的第 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;}
}

总结

通过拆分代码,我们可以清晰地看到每个部分的功能:

  1. 数据初始化。
  2. 按价格排序并分组。
  3. 对分组内的产品排序。
  4. 对分组的键排序。
  5. 按顺序取出每组的第 i 个元素。
  6. 按每组的第 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 运行程序&#xff0c;查看结果 4. 实战小结 1. 实战概述 本次实战项目旨在通过编写Python爬虫程序&#xff0c;抓取深圳Q房网上的二手房房源信息。我们将分析网页结构&#xff0c;…...

Ansible自动化运维(五) 运维实战

Ansible自动化运维这部分我将会分为五个部分来为大家讲解 &#xff08;一&#xff09;介绍、无密钥登录、安装部署、设置主机清单 &#xff08;二&#xff09;Ansible 中的 ad-hoc 模式 模块详解&#xff08;15&#xff09;个 &#xff08;三&#xff09;Playbook 模式详解 …...

K-means算法的python实现

K-means算法步骤 初始化质心&#xff1a;输入初始的质心位置。分配样本&#xff1a;将每个数据点分配到离它最近的质心对应的簇中。更新质心&#xff1a;对每个簇中的所有数据点&#xff0c;计算它们的均值&#xff0c;并将均值更新为新的质心。重复步骤2和3&#xff0c;直到质…...

客户端(浏览器)vue3本地预览txt,doc,docx,pptx,pdf,xlsx,csv,

预览文件 1、入口文件preview/index.vue2、预览txt3、预览doc4、预览pdf5、预览pptx6、预览xlsx7、预览csv 1、入口文件preview/index.vue 预览样式&#xff0c;如pdf 文件目录如图所示&#xff1a; 代码如下 <template><div class"preview-wrap" ref&…...

[SZ901]JTAG高速下载设置(53Mhz)

SZ901最高支持JTAG 53MHz的时钟频率&#xff0c;下载bit文件和固化程序的速度提升非常明显。 首先设置参数 1&#xff0c;将JTAG0 分频系数修改为3 2&#xff0c;设置参数&#xff0c;更新参数。&#xff08;完成&#xff09; 打开VIVADO VIVADO 正常识别FPGA&#xff0c;速…...

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 命令是用于列出目录内容。用户可以查看指定目录下的文件和子目录&#xff0c;还可以获取有关这些文件和子目录的详细信息。 基本语法&#xff1a; ls [选项] [目录]如果不指定目录&#xff0c;ls 将列出当前工作目录下的内容。 01、-a 或 --all ls…...

React Native状态管理器Redux、MobX、Context API、useState

Redux、MobX、Context API、useState都是React中用于状态管理的工具&#xff0c;但它们各自有不同的特点和使用场景。 Redux 介绍&#xff1a; Redux是一个JavaScript状态管理库&#xff0c;最初由Dan Abramov和Andrew Clark于2015年开发。它基于Flux架构&#xff0c;强调状态…...

Three.js资源-模型下载网站

在使用 Three.js 进行 3D 开发时&#xff0c;拥有丰富的模型资源库可以大大提升开发效率和作品质量。以下是一些推荐的 Three.js 模型下载网站&#xff0c;它们提供了各种类型的 3D 模型&#xff0c;适合不同项目需求。无论你是需要逼真的建筑模型&#xff0c;还是简单的几何体…...

linux 添加默认网关

在linux 可以使用 route 命令添加默认网关&#xff0c;假设添加的默认网关是192.168.159.2 添加方式如下&#xff1a; route add default gw 192.168.159.2 以上命令只需要把add 改成 del &#xff0c;就能删除刚才添加的路由 route del default gw 192.168.159.2 #该命…...

【学习笔记】深入浅出详解Pytorch中的View, reshape, unfold,flatten等方法。

文章目录 一、写在前面二、Reshape&#xff08;一&#xff09;用法&#xff08;二&#xff09;代码展示 三、Unfold&#xff08;一&#xff09;torch.unfold 的基本概念&#xff08;二&#xff09;torch.unfold 的工作原理&#xff08;三&#xff09; 示例代码&#xff08;四&a…...

CTFHUB-web(SSRF)

内网访问 点击进入环境&#xff0c;输入 http://127.0.0.1/flag.php 伪协议读取文件 /?urlfile:///var/www/html/flag.php 右击查看页面源代码 端口扫描 1.根据题目提示我们知道端口号在8000-9000之间,使用bp抓包并进行爆破 POST请求 点击环境&#xff0c;访问flag.php 查看页…...

分解质因数

给定 n个正整数 &#xff0c;将每个数分解质因数&#xff0c;并按照质因数从小到大的顺序输出每个质因数的底数和指数。 输入格式 第一行包含整数 n 接下来 n行&#xff0c;每行包含一个正整数 。 输出格式 对于每个正整数 &#xff0c;按照从小到大的顺序输出其分解质因数后&…...

前景物体提取

参考&#xff1a;精选课&#xff1a;C完整的实现双目摄像头图像采集、双目摄像头畸变矫正、前景物体提取、生成视差图、深度图、PCL点云图 前景物体提取是计算机视觉中的一个重要技术&#xff0c;可以用于视频监控、虚拟现实和计算机视觉等领域。 1.前景物体提取的原理 前景…...

Kotlin复习

一、Kotlin类型 1.整数 2.浮点 显示转换&#xff1a; 所有数字类型都支持转换为其他类型&#xff0c;但是转换前会检测长度。 toByte(): Byte toShort(): Short toInt(): Int toLong(): Long toFloat(): Float toDouble(): Double 不同进制的数字表示方法&#xff08;为了提高…...

【AI日记】24.12.17 kaggle 比赛 2-6 | 把做饭看成一种游戏 | 咖喱牛肉

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 参加&#xff1a;kaggle 比赛 Regression with an Insurance Dataset时间&#xff1a;9 小时睡得好很重要 读书 书名&#xff1a;富兰克林自传时间&#xff1a;0.5 小时阅读原因&#xff1a;100 美元纸…...

操作系统(14)请求分页

前言 操作系统中的请求分页&#xff0c;也称为页式虚拟存储管理&#xff0c;是建立在基本分页基础上&#xff0c;为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能的一种内存管理技术。 一、基本概念 分页&#xff1a;将进程的逻辑地址空间分成若干个大小相等的页&am…...

uniapp navigateTo、redirectTo、reLaunch等页面路由跳转方法的区别

uni.switchTab 跳转到 tabBar 页面&#xff0c;并关闭其他所有非 tabBar 页面 // app.json {"tabBar": {"list": [{"pagePath": "index","text": "首页"},{"pagePath": "other","text&…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...