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

Java模拟rank() over()函数获取分组排名的方法设计及实现

背景

考试批次班级姓名语文
202302三年一班张小明130.00
202302三年一班王二小128.00
202302三年一班谢春花136.00
202302三年二班冯世杰129.00
202302三年二班马功成130.00
202302三年二班魏翩翩136.00

假设我们有如上数据,现在有一个需求需要统计各学生语文单科成绩在班级中的排名和全年段排名,你会如何实现?

很容易的我们想到了 rank() over() 实现

over()是分析函数,可以和 rank()、 dense_rank() 、 row_number() 配合使用。
复制代码

使用语法如下:

RANK() OVER(PARTITION BY COLUMN ORDER BY COLUMN)
dense_rank() OVER(PARTITION BY COLUMN ORDER BY COLUMN)
ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN)
复制代码

解释:partition by用于给结果集分组,如果没有指定那么它把整个结果集作为一个分组。

  1. rank()涵数主要用于排序,并给出序号 ,对于排序并列的数据给予相同序号,并空出并列所占的名次。
  2. dense_rank() 功能同rank()一样,区别在于不空出并列所占的名次
  3. row_number()涵数则是按照顺序依次使用 ,不考虑并列

rank 结果为 1,2,2,4 dense_rank 结果为 1,2,2,3 row_number 结果为 1,2,3,4

实际应用中,会存在数据从其他外部系统接入且数据量不大等多种情况,那么使用Java代码的方式实现分组排名的功能则显得更加方便。

详细设计及实现

排序定义类 OrderBy

public class OrderBy {private String orderByEL;/*** 是否升序*/private boolean ascend;public OrderBy(){//默认升序this.ascend = true;}public String orderByEL(){return this.orderByEL;}public OrderBy orderByEL(String orderByEL){this.orderByEL = orderByEL;return this;}public OrderBy ascend(boolean ascend){this.ascend = ascend;return this;}public boolean ascend(){return this.ascend;}
}
复制代码

该类定义了如下属性:

  1. 排序的fileld
  2. 是否升序

获取排名方法

该方法定义如下:

<T> void rankOver(List<T> dataList, String[] partitionByFields, List<OrderBy> orderByList, String resultField, int rankType);
复制代码

该方法提供了5个入参:

  1. dataList 排序的数据集
  2. partitionByFields 分组field的数组
  3. orderByList 排序字段集合
  4. resultField 排名结果存放的字段
  5. rankType 排名方式
    • 1:不考虑并列(row_number 结果为 1,2,3,4)
    • 2:考虑并列,空出并列所占的名次(rank 结果为 1,2,2,4)
    • 3:考虑并列,不空出并列所占的名次(dense_rank 1,2,2,3)

该方法具体实现如下

    public static <T> void rankOver(List<T> dataList, String[] partitionByFields, List<OrderBy> orderByList, String resultField, int rankType) {if (CollectionUtils.isEmpty(orderByList)) {return;}//STEP_01 剔除掉不参与排名的数据List<T> tempList = new ArrayList<>();for (T data : dataList) {boolean part = true;for (OrderBy rptOrderBy : orderByList) {Object o1 = executeSpEL(rptOrderBy.orderByEL(), data);if (o1 == null) {//参与排序的值为null的话则不参与排名part = false;break;}}if (part) {tempList.add(data);}}if (CollectionUtils.isEmpty(tempList)) {return;}//STEP_02 分组Map<String, List<T>> groupMap = group(tempList, null, partitionByFields);for (List<T> groupDataList : groupMap.values()) {order(orderByList, groupDataList);if (rankType == 1) {int rank = 1;for (T temp : groupDataList) {setFieldValue(temp, resultField, rank);rank++;}} else {int prevRank = Integer.MIN_VALUE;int size = groupDataList.size();for (int i = 0; i < size; i++) {T current = groupDataList.get(i);if (i == 0) {//第一名setFieldValue(current, resultField, 1);prevRank = 1;} else {T prev = groupDataList.get(i - 1);boolean sameRankWithPrev = true;//并列排名for (OrderBy rptOrderBy : orderByList) {Object o1 = executeSpEL(rptOrderBy.orderByEL(), current);Object o2 = executeSpEL(rptOrderBy.orderByEL(), prev);if (!o1.equals(o2)) {sameRankWithPrev = false;break;}}if (sameRankWithPrev) {setFieldValue(current, resultField, getFieldValue(prev, resultField));if (rankType == 2) {++prevRank;}} else {setFieldValue(current, resultField, ++prevRank);}}}}}}
复制代码

使用案例

定义一个学生类:

public class Student {private String batch;private String banji;private String name;private Double yuwen;//extraprivate Integer rank1;private Integer rank2;public Student(String batch, String banji, String name, Double yuwen) {this.batch = batch;this.banji = banji;this.name = name;this.yuwen = yuwen;}
}复制代码

我们写一个方法,返回如下数据:

public List<Student> getDataList() {List<Student> dataList = new ArrayList<>();dataList.add(new Student("202302", "三年一班", "张小明", 130.0));dataList.add(new Student("202302", "三年一班", "王二小", 128.0));dataList.add(new Student("202302", "三年一班", "谢春花", 136.0));dataList.add(new Student("202302", "三年二班", "冯世杰", 129.0));dataList.add(new Student("202302", "三年二班", "马功成", 130.0));dataList.add(new Student("202302", "三年二班", "魏翩翩", 136.0));return dataList;
}
复制代码

获取学生语文成绩的班级排名和年段排名,排名采用并列并空出并列所占用名次的方式。

List<Student> dataList = getDataList();
List<OrderBy> orderByList = new ArrayList<>();
orderByList.add(new OrderBy().orderByEL("yuwen").ascend(false));
//获取全校排名
DataProcessUtil.rankOver(dataList, new String[]{"batch"}, orderByList, "rank1", 2);
//获取班级排名
DataProcessUtil.rankOver(dataList, new String[]{"batch", "banji"}, orderByList, "rank2", 2);
log("语文单科成绩排名情况如下:");Map<String, List<Student>> groupMap = DataProcessUtil.group(dataList, null, new String[]{"batch"});
for (Map.Entry<String, List<Student>> entry : groupMap.entrySet()) {log("考试批次:" + entry.getKey());for (Student s : entry.getValue()) {log(String.format("班级:%s 学生:%s 语文成绩:%s 班级排名:%s 全校排名:%s", s.getBanji(), s.getName(), s.getYuwen(), s.getRank2(), s.getRank1()));}log("");
}
复制代码

结果如下:

语文单科成绩排名情况如下:
考试批次:202302
班级:三年一班 学生:张小明 语文成绩:130.0 班级排名:2 全校排名:3
班级:三年一班 学生:王二小 语文成绩:128.0 班级排名:3 全校排名:6
班级:三年一班 学生:谢春花 语文成绩:136.0 班级排名:1 全校排名:1
班级:三年二班 学生:冯世杰 语文成绩:129.0 班级排名:3 全校排名:5
班级:三年二班 学生:马功成 语文成绩:130.0 班级排名:2 全校排名:3
班级:三年二班 学生:魏翩翩 语文成绩:136.0 班级排名:1 全校排名:1
复制代码

可以看到全校排名中 有两个并列第一名 两个并列第三名,且空出了并列所占用的名次2 和 名次4

相关文章:

Java模拟rank() over()函数获取分组排名的方法设计及实现

背景 考试批次班级姓名语文202302三年一班张小明130.00202302三年一班王二小128.00202302三年一班谢春花136.00202302三年二班冯世杰129.00202302三年二班马功成130.00202302三年二班魏翩翩136.00 假设我们有如上数据&#xff0c;现在有一个需求需要统计各学生语文单科成绩在班…...

不用但一定要懂 ---- iOS 之 响应链、传递链 与 手势识别

iOS 事件的主要由&#xff1a;响应连 和 传递链 构成。一般事件先通过传递链&#xff0c;传递下去。响应链&#xff0c;如果上层不能响应&#xff0c;那么一层一层通过响应链找到能响应的UIResponse。 响应链&#xff1a;由最基础的view向系统传递&#xff0c;first view ->…...

观早报 | 特斯拉储能超级工厂落沪;“华尔街之狼”募资550亿

今日要闻&#xff1a;京东拟今年发布千亿级产业大模型&#xff1b;特斯拉储能超级工厂落沪&#xff1b;“华尔街之狼”募资550亿&#xff1b;英特尔落户海南三亚&#xff1b;日本人要搞二次元老婆版 ChatGPT京东拟今年发布千亿级产业大模型 据《科创板日报》消息&#xff0c;京…...

SpringCloud集成Seata saga模式案例

文章目录一、前言二、Seata saga模式介绍1、示例状态图2、“状态机”介绍1&#xff09;“状态机”属性2&#xff09;“状态”属性3&#xff09;更多状态相关内容三、SpringCloud 集成 seata saga1、saga模式状态机相关信息1&#xff09;状态机配置相关的三个表2&#xff09;状态…...

逍遥自在学C语言 | 位运算符的高级用法

前言 在上一篇文章中&#xff0c;我们介绍了&运算符的基础用法&#xff0c;本篇文章&#xff0c;我们将介绍& 运算符的一些高级用法。 一、人物简介 第一位闪亮登场&#xff0c;有请今后会一直教我们C语言的老师 —— 自在。 第二位上场的是和我们一起学习的小白程序…...

Java实现输入行数打印取缔字符,打印金字塔三角形的两个代码程序

目录 前言 一、实现输入行数&#xff0c;打印取缔字符 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图 二、打印金字塔三角形 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图​​​​​​​ 前言 1.因多重原因&#xff0c;本博文有…...

express项目的创建

前言 前端开发者若要进行后端开发&#xff0c;大多都会选择node.js&#xff0c;在node生态下是有大量框架的&#xff0c;其中最受新手喜爱的便是老牌的express.js&#xff0c;接下来我们就从零创建一个express项目。 安装node 在这里&#xff1a;https://nodejs.org/dist/v16…...

RK3399平台开发系列讲解(基础篇)Linux 传统间隔定时器

🚀返回专栏总目录 文章目录 一、设置间隔定时器 setitimer()二、查询定时器状态 getitimer()三、更简单的定时接口 alarm()四、传统定时器的应用4.1、为阻塞操作设置超时4.2、性能剖析五、传统定时器的局限性沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将详细…...

Kafka 3.4.0 kraft 集群搭建

文章目录简介基础环境服务器三台安装下载安装初始化集群启动集群验证创建Topic查看Topic详情简介 Apache 软件基金会发布了包含许多新特性和改进的 Kafka 3.3.1。这是第一个标志着可以在生产环境中使用 KRaft&#xff08;Kafka Raft&#xff09;共识协议的版本。在几年的开发过…...

微信小程序 iphone14 css mask 使用图片实现遮照 疑似 no-repeat 失效

1. 将图片转为 换成svg类型 2. css设置属性时书写顺序&#xff08;如果顺序不对会导致展示问题 T T 奇妙的bug&#xff09; .water-inner {-webkit-mask-image: url("./water-black.svg");mask-image: url("./water-black.svg");-webkit-mask-size: cont…...

密码学实践-04

密码强度 你要揭榜的任务非常简单&#xff0c;内容如下。 用户输入口令后&#xff0c;请进行强度检测&#xff1a; 等级三种&#xff1a;强&#xff0c;中&#xff0c;弱 1、口令长度小于等于8位&#xff0c;并且纯小写英文或大写英文&#xff0c;弱 2、口令长度小于等于8位&am…...

SpringBoot整合swagger实现接口管理并设置加密访问

pom.xml pom.xml文件加入swagger <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>com.github.xiaoymin&l…...

C语言单例模式-实现高性能日志管理器

C语言单例模式-实现高性能日志管理器 代码中&#xff0c;使用了单例模式来创建日志管理器对象&#xff0c;保证了整个程序中只有一个日志管理器对象。 日志管理器中包含了日志文件指针、日志级别、互斥锁等成员&#xff0c;通过这些成员来实现日志的写入和级别控制。 在主函数…...

Flutter - flutter项目添加 Web 支持

demo 地址: https://github.com/iotjin/jh_flutter_demo 代码不定时更新&#xff0c;请前往github查看最新代码 参考&#xff1a; 官方&#xff1a;构建 Flutter Web 应用 Flutter Desktop Support flutter项目添加 Web 支持 在项目的根目录下运行&#xff1a;flutter create …...

关键词数据分析-搜索词和关键词分析工具

要搜索热门关键词获取&#xff0c;可以采用以下几种方法&#xff1a; 使用百度指数&#xff1a;百度指数是一个实用的工具&#xff0c;可用于查看关键词的热度趋势、搜索量等数据。在百度指数中&#xff0c;您可以输入您要搜索的关键词&#xff0c;并查看近期的相关数据。这可以…...

SpringCloud微服务技术栈之网关服务Gateway

文章目录SpringCloud微服务技术栈之网关服务Gateway前言网关服务Gateway的基本概念Gateway的体系结构Gateway的主要功能网关服务Gateway的架构设计架构设计方案示例代码网关服务Gateway的实践操作1. 创建工程2. 配置路由规则3. 实现过滤器4. 集成服务注册中心5. 启动网关服务器…...

什么原因导致了儿童自闭症?跟父母养育有关吗?

导致儿童自闭症的原因是什么&#xff1f;这和父母的抚养有关吗&#xff1f;学习教育孩子的方法&#xff0c;让孩子快乐健康地成长&#xff0c;是家庭和孩子生活中的一件重要事情。不良的环境和错误的教育会导致儿童自闭症&#xff0c;这是真的吗&#xff1f;自闭症&#xff0c;…...

抽象轻松web

不断学习&#xff0c;不断进步&#xff0c;才能不被替代 只有你的不可被替代性才是价值所在 千变万化的叶子 根只有一个 ----2023年4月7日 弹性盒布局的作用其实是定位 我们设置弹性盒子的时候目的是为了让元素放在页面中的某个位置&#xff0c;从而达到布局的效果 定位的本质…...

如何获取系统下目录的文件系统类型

最近看到一个问题&#xff0c;如何获取当前系统的文件类型&#xff1f; 这个时候就要介绍下/proc/mounts文件&#xff1a;这个文件以/etc/mtab文件的格式给出当前系统所安装的文件系统信息。同时也能反映出任何手工安装从而在/etc/mtab文件中没有包含的文件系统。 我们可以通…...

【Linux】GCC编译器的使用

目录 前言&#xff1a; 一、GCC编译过程 1.预处理&#xff1a; 2.编译 3.汇编 4.链接 二、制作、使用动态库和静态库 1.静态库 2.动态库 三、好用的选项 1.gcc -E main.c 2.gcc -E -dM main.c > 1.txt 3.gcc -Wp,-MD,abc.dep -c -o main.o main.c 4.echo main(){}| …...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...