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

Java stream流支持多字段排序

背景

对于排序而言,比较常见的场景是前端传递所需的排序字段名和排序方向,然后通过stream流或者数据库来实现排序.
为动态接收参数,继承Map来支持多字段传入.另外stream流原生的sorted写起来相对比较繁琐,通过compartor方法封装构建多字段排序的逻辑.具体就是通过反射拿到对应字段的值,然后利用Compartor的comparing和thenComparing完成多字段排序.

代码

具体代码和测试结果如下

package xyz.yq56;import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;import cn.hutool.core.util.ReflectUtil;
import lombok.Data;/*** 封装Map接收前端排序参数,并提供compartor,方便构建stream流sorted所需的Comparator* <pre>*     示例:*     {*         "fieldName": "ascend",*         "fieldName2": "descend"*     }* </pre>** <pre>*     1. key 是排序字段*     2. value 是排序方向,可选值 ascend/descend 或者 asc/desc*     3. 排序字段属性需符合java的get规范,其中使用了反射获取field对应的get方法*     4. 排序字段的类型必须实现Comparable接口,否则抛出异常The field xx does not implement Comparable interface*     5. 注意这里用的是LinkedHashMap,保证排序参数的顺序.如果是HashMap,排序参数的顺序可能会丢失,甚至反过来*     6. 依赖了hutool的ReflectUtil,后续尽量移除此依赖* </pre>** @author yi qiang* @date 2024-07-23 16:28:52*/
@SuppressWarnings("all")
public class SortMap extends LinkedHashMap<String, String> {public Comparator compartor() {if (this.isEmpty()) {return null;}Comparator comparator = null;// 遍历排序参数,构建comparator// 可以用reduce,但是感觉还没三元表达式清晰for (Map.Entry<String, String> entry : this.entrySet()) {comparator = (comparator == null) ?getTempComparator(entry.getKey(), entry.getValue()) ://多字段排序,第二个字段开始就要使用thenComparingcomparator.thenComparing(getTempComparator(entry.getKey(), entry.getValue()));}return comparator;}private Comparator getTempComparator(String fieldName, String direction) {if ("descend".equalsIgnoreCase(direction) || "desc".equalsIgnoreCase(direction)) {return Comparator.comparing(getKeyExtractor(fieldName), Comparator.reverseOrder());}return Comparator.comparing(getKeyExtractor(fieldName));}/*** 排序属性值的映射函数*/private Function getKeyExtractor(String fieldName) {return ele -> {Object o = ReflectUtil.getFieldValue(ele, fieldName);if (o instanceof Comparable) {return (Comparable) o;}throw new RuntimeException("The field " + fieldName + " does not implement Comparable interface");};}// 暂时未经过严格测试,比如父类属性,先不处理//    private static Object getFieldValue(Object ele,String fieldName) {//        try {//            Field declaredField = ele.getClass().getDeclaredField(fieldName);//            declaredField.setAccessible(true);//            return declaredField.get(ele);//        } catch (Exception ex) {//            return null;//        }//    }public static void main(String[] args) {List<Test> tests = new ArrayList<>();Test test = new Test();test.setL(1);test.setDate(new Date());test.setS("c");tests.add(test);Test test1 = new Test();test1.setL(2);test1.setDate(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24));test1.setS("a");tests.add(test1);Test test2 = new Test();test2.setL(2);test2.setDate(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24));test2.setS("b");test2.setTest2(new Test2());tests.add(test2);SortMap sortMap = new SortMap();sortMap.put("l", "descend");sortMap.put("s", "descend");//测试Comparable接口未实现//sortMap.put("test2", "ascend");tests.stream().sorted(sortMap.compartor()).forEach(System.out::println);}@Datapublic static class Test {private long l;private String s;private Date date;private Test2 test2;}@Datapublic static class Test2 {private long l;private String s;}
}

运行结果
在这里插入图片描述
如果此工具能帮到大家,请动动手点个赞.

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【力扣】746.使用最小花费爬楼梯
  • Mysql 脚本转换为drawio ER 脚本
  • 使用LaTeX分章节撰写文档
  • LVS集群实现四层负载均衡详解(以nat,dr模式为例)
  • 【SQL Server】端口安全配置:SQL Server的安全最佳实践与防火墙规则配置
  • 前端(五):前端工程化
  • 代码随想录算法训练营第二十一天 | 77. 组合, 216.组合总和III , 17.电话号码的字母组合
  • mysql group_concat and laravel group_concat使用
  • 短波通信:保底手段
  • mysql 字符串转数组
  • AI智能助手商业系统软件源码(IMYAI智能助手) AI换脸/智能体GPTs应用/AI视频生成/AI绘画/文档分析/GPT-4o模型支持
  • el-dialog设置对话框高度,禁用点击关闭对话框
  • java里的序列化反序列化、HttpMessageConverter、Jackson、消息转化器、对象转化器...都是啥?
  • 【QT 5 QT 6 构建工具qmake-cmake-和-软件编译器MSVCxxxvs MinGWxxx说明】
  • 《UE5_C++多人TPS完整教程》学习笔记32 ——《P33 动画蓝图(Animation Blueprint)》
  • co.js - 让异步代码同步化
  • JavaScript设计模式之工厂模式
  • Python进阶细节
  • vuex 学习笔记 01
  • Wamp集成环境 添加PHP的新版本
  • Webpack 4 学习01(基础配置)
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 计算机常识 - 收藏集 - 掘金
  • 算法之不定期更新(一)(2018-04-12)
  • 微信支付JSAPI,实测!终极方案
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • No resource identifier found for attribute,RxJava之zip操作符
  • gunicorn工作原理
  • 大数据全解:定义、价值及挑战
  • 函数计算新功能-----支持C#函数
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • # 安徽锐锋科技IDMS系统简介
  • ### RabbitMQ五种工作模式:
  • #100天计划# 2013年9月29日
  • #数据结构 笔记三
  • (4)事件处理——(7)简单事件(Simple events)
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (二)Eureka服务搭建,服务注册,服务发现
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (十)T检验-第一部分
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (四)软件性能测试
  • (转)ABI是什么
  • .gitignore
  • .Net 8.0 新的变化
  • .net core 6 集成和使用 mongodb
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .net操作Excel出错解决
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • .ui文件相关
  • :中兴通讯为何成功
  • []使用 Tortoise SVN 创建 Externals 外部引用目录
  • [20150321]索引空块的问题.txt