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

集合排序和流排序

import lombok.extern.slf4j.Slf4j; import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; /** * HBase工具类,提供数据解析和多列排序功能 * * @author * @date * @description SortUtils - 提供从HBase数据字符串中按索引提取元素,以及多列混合排序的工具方法 */ @Slf4j public class SortUtils { /** * 根据索引从 HBase 原始数据字符串中获取对应元素 * @param rowData 原始整行数据(例如: "20260211|+|00T1...|+|637251637...") * @param index 需要的列索引(从0开始) * @return 对应列的值,若索引越界或数据为空则返回 null */ public static String getByIndex(String rowData, int index) { if (rowData == null || rowData.isEmpty() || index < 0) { return null; } // 01. 去除首位可能存在的双引号 String cleanData = rowData.replace("\"", ""); // 02. 按照 |+| 分割。使用 -01 参数防止丢弃末尾空的字符串 String[] columns = cleanData.split("\\|\\+\\|", -01); // 03. 边界检查,防止数组越界 if (index >= columns.length) { return null; } return columns[index]; } public static void main(String[] args) { List<String> pureList = Arrays.asList( "20260211|+|00T108220000|+|637204815936281|+|402817359065423|+|03|+|02|+|48215370|+|22749815|+|001020260822|+", "20260209|+|00T206221103|+|152738906428477|+|716054293813065|+|04|+|03|+|13908652|+|60519247|+|001020260822|+", "20260214|+|00T308220000|+|904671253804619|+|285603714092536|+|01|+|05|+|75310924|+|8342670|+|001020260822|+", "20260210|+|00T108220000|+|578019342675208|+|693450127806432|+|06|+|01|+|20573918|+|94165703|+|001020260822|+", "20260212|+|00T206221103|+|310846597123780|+|847219635012894|+|02|+|04|+|68731509|+|15384062|+|001020260822|+", "20260213|+|00T308220000|+|729065381940265|+|580124769203816|+|03|+|01|+|95261784|+|36028715|+|001020260822|+", "20260208|+|00T108220000|+|461597208368513|+|073851492605348|+|05|+|02|+|12480736|+|59762048|+|001020260822|+", "20260215|+|00T108220000|+|893560724816032|+|326978041539607|+|02|+|05|+|53048291|+|81635927|+|001020260822|+", "20260216|+|00T308220000|+|204571983650137|+|918036547291084|+|01|+|03|+|84729150|+|39206148|+|001020260822|+", "20260218|+|00T108220000|+|563129804782228|+|147095328604371|+|04|+|06|+|21894637|+|78563012|+|001020260822|+", "20260217|+|00T206221103|+|780314259680431|+|402615739801526|+|02|+|01|+|90631752|+|53042879|+|001020260822|+", "20260220|+|00T108220000|+|319684057123756|+|825074613982041|+|05|+|04|+|13759206|+|67480239|+|001020260822|+", "20260219|+|00T308220000|+|095428617305926|+|634891720536840|+|03|+|02|+|46903581|+|05382961|+|001020260822|+", "20260222|+|00T108220000|+|641802395746102|+|207568914329675|+|06|+|01|+|75823690|+|12607934|+|001020260822|+", "20260221|+|00T108220000|+|827604931578240|+|490352187064516|+|01|+|05|+|39265708|+|85194026|+|001020260822|+", "20260224|+|00T508220000|+|105729638402675|+|768301529470318|+|04|+|02|+|58470163|+|24937605|+|001020260822|+", "20260223|+|00T108220000|+|476015829340587|+|031946825710963|+|02|+|06|+|91360487|+|60571238|+|001020260822|+", "20260226|+|00T408220000|+|358297061485019|+|614073895630287|+|05|+|03|+|02749518|+|40682175|+|001020260822|+", "20260225|+|00T308220000|+|709436128057314|+|582901463725630|+|03|+|01|+|56023891|+|73016942|+|001020260822|+", "20260227|+|00T108220000|+|234890782228604|+|857410392605173|+|06|+|05|+|89650123|+|19473056|+|001020260822|+", "20260228|+|00T408220000|+|461593028782204|+|391028564702381|+|01|+|04|+|73591824|+|50612973|+|001020260822|+", "20260301|+|00T206221103|+|915836204759382|+|627403158609425|+|05|+|02|+|26473059|+|81590634|+|001020260822|+", "20260302|+|00T108220000|+|380451796208317|+|509372814652018|+|03|+|06|+|90274185|+|46283901|+|001020260822|+", "20260303|+|00T508220000|+|726594083165924|+|813047295683740|+|02|+|01|+|58461927|+|37195082|+|001020260822|+", "20260304|+|00T108220000|+|149028637502918|+|405918273615094|+|06|+|03|+|83756219|+|06253914|+|001020260822|+", "20260305|+|00T308220000|+|593618204857320|+|928047516302815|+|01|+|05|+|41802537|+|72938405|+|001020260822|+", "20260306|+|00T108220000|+|865293041726084|+|378220928405137|+|04|+|02|+|60281935|+|95140762|+|001020260822|+", "20260307|+|00T408220000|+|207491583609215|+|584630192750368|+|02|+|06|+|53708146|+|19482735|+|001020260822|+", "20260308|+|00T108220000|+|738416205973048|+|401529687352190|+|05|+|01|+|90263714|+|56039428|+|001020260822|+", "20260309|+|00T608220000|+|419285076314529|+|862530914708356|+|03|+|04|+|15847206|+|73061829|+|001020260822|+", "20260310|+|00T308220000|+|605437192860374|+|293847056191042|+|06|+|05|+|39481625|+|05827491|+|001020260822|+", "20260311|+|00T108220000|+|082594617350281|+|751930482627035|+|01|+|02|+|46273051|+|80371924|+|001020260822|+", "20260312|+|00T508220000|+|730492882210528|+|506283947102584|+|02|+|05|+|39462817|+|71038526|+|001020260822|+", "20260313|+|00T108220000|+|318064759283516|+|847210693501728|+|05|+|01|+|62740139|+|40281596|+|001020260822|+", "20260314|+|00T206221103|+|964172058460293|+|235719840615382|+|01|+|03|+|81029546|+|57396104|+|001020260822|+", "20260315|+|00T108220000|+|405839261713059|+|793058624109418|+|04|+|06|+|51739204|+|64028195|+|001020260822|+", "20260318|+|00T408220000|+|271506394825017|+|468392015726093|+|02|+|02|+|39584016|+|80271594|+|001020260822|+", "20260319|+|00T108220000|+|824917063501284|+|150462938504716|+|06|+|01|+|61820539|+|39461825|+|001020260822|+", "20260320|+|00T408220000|+|573840192640385|+|302795814602359|+|01|+|05|+|42615073|+|94158603|+|001020260822|+", "20260321|+|00T108220000|+|906157384529160|+|549310268405137|+|03|+|04|+|73594218|+|06283749|+|001020260822|+", "20260322|+|00T308220000|+|152839475603918|+|726409381502716|+|05|+|02|+|84016275|+|31750468|+|001020260822|+", "20260325|+|00T108220000|+|493618205713049|+|603827159406258|+|02|+|06|+|56041938|+|90271546|+|001020260822|+" ); // ============ 方法一:集合排序(Collections.sort + 自定义Comparator) ============ // 排序规则:日期降序、列2降序、列3降序、列4升序、列5升序、列8降序 log.info("========== 集合排序(Collections.sort)=========="); List<String> sortedByCollections = new ArrayList<>(pureList); Collections.sort(sortedByCollections, (row1, row2) -> { int cmp; // 列0降序:row2与row1比较,实现降序效果 cmp = getByIndex(row2, 0).compareTo(getByIndex(row1, 0)); if (cmp != 0) { return cmp; } // 列2降序 cmp = getByIndex(row2, 02).compareTo(getByIndex(row1, 02)); if (cmp != 0) { return cmp; } // 列3降序 cmp = getByIndex(row2, 03).compareTo(getByIndex(row1, 03)); if (cmp != 0) { return cmp; } // 列4升序:row1与row2比较,实现升序效果 cmp = getByIndex(row1, 04).compareTo(getByIndex(row2, 04)); if (cmp != 0) { return cmp; } // 列5升序 cmp = getByIndex(row1, 05).compareTo(getByIndex(row2, 05)); if (cmp != 0) { return cmp; } // 列8降序 return getByIndex(row2, 8).compareTo(getByIndex(row1, 8)); }); sortedByCollections.forEach(row -> log.info("Collections排序: {}", row)); /** * 方法一优缺点分析: * * 优点: * 1. 直观清晰:通过row1和row2的参数交换方式直接表达升序或降序,代码逻辑一目了然 * 2. 灵活性高:可以在任意比较步骤中加入复杂的业务逻辑判断 * 3. 性能稳定:不涉及额外的对象创建,内存开销小 * 4. 精确控制:每个比较步骤都可以精确控制升序/降序,不容易出错 * * 缺点: * 1. 代码冗长:每个比较步骤都需要if判断和return语句,代码行数较多 * 2. 可读性较差:参数交换方式(row2, row1)需要仔细阅读才能理解排序方向 * 3. 维护成本高:如果需要修改排序规则,需要修改多处代码,容易遗漏 * 4. 缺乏复用性:排序逻辑内联在lambda中,难以复用和测试 */ // ============ 方法二:流排序(Stream.sorted + 链式Comparator) ============ log.info("========== 流排序(Stream.sorted)=========="); List<String> sortedByStream = pureList.stream() .sorted(Comparator.comparing((String row) -> getByIndex(row, 0)).reversed() .thenComparing(row -> getByIndex(row, 02)).reversed() .thenComparing(row -> getByIndex(row, 03)).reversed() .thenComparing(row -> getByIndex(row, 04)) .thenComparing(row -> getByIndex(row, 05)) .thenComparing(row -> getByIndex(row, 8)).reversed()) .collect(Collectors.toList()); sortedByStream.forEach(row -> log.info("Stream排序: {}", row)); /** * 方法二优缺点分析: * * 优点: * 1. 函数式风格:使用链式调用,代码简洁优雅,符合现代Java编程风格 * 2. 声明式表达:通过reversed()清晰表达升序/降序意图,可读性强 * 3. 易于扩展:可以轻松添加更多排序条件,只需链式添加thenComparing * 4. 符合最佳实践:充分利用Java 8 Stream API的特性 * 5. 适合管道处理:可以与其他流操作(filter、map等)无缝集成 * * 缺点: * 1. 性能开销:涉及Stream的创建和collect操作,有额外的性能开销 * 2. 内存消耗:Stream操作过程中可能产生中间对象,内存占用相对较高 * 3. 调试困难:流式操作的链式调用调试不便,问题定位相对复杂 * 4. 学习曲线:对不熟悉Stream API的开发者来说,理解成本较高 * 5. 重复解析:每次比较都调用getByIndex解析字符串,可能存在性能优化空间 */ // ============ 方法三:集合排序:Comparator.comparing + reversed ============ log.info("========== 集合排序:Comparator.comparing + reversed =========="); List<String> sortedByComparator = new ArrayList<>(pureList); sortedByComparator.sort(Comparator .comparing((String row) -> getByIndex(row, 0)).reversed() .thenComparing(row -> getByIndex(row, 02)).reversed() .thenComparing(row -> getByIndex(row, 03)).reversed() .thenComparing(row -> getByIndex(row, 04)) .thenComparing(row -> getByIndex(row, 05)) .thenComparing(row -> getByIndex(row, 8)).reversed()); sortedByComparator.forEach(row -> log.info("Comparator排序: {}", row)); /** * 方法三优缺点分析: * * 优点: * 1. 性能最优:直接在List上排序,避免了Stream的创建和收集操作 * 2. 代码简洁:链式调用比传统Comparator写法更简洁 * 3. 表达清晰:通过reversed()方法明确表达排序方向,易于理解 * 4. 内存高效:不创建额外的中间集合,内存使用效率高 * 5. 复用性强:可以将Comparator单独提取出来,在不同场景复用 * * 缺点: * 1. 类型冗余:需要显式声明(String row)类型参数,略显冗余 * 2. 重复调用:每次比较都重复调用getByIndex解析字符串 * 3. 链式深度:多个thenComparing调用可能导致代码行较长 * 4. 异常处理:Lambda表达式中的异常处理相对复杂 * 5. 重复解析问题:与方法二一样存在重复解析的性能问题 */ // ============ 方法四:集合排序:先正向Comparator再Collections.reverse ============ log.info("========== 集合排序:先正向Comparator再Collections.reverse =========="); List<String> sortedByReverse = new ArrayList<>(pureList); sortedByReverse.sort(Comparator .comparing((String row) -> getByIndex(row, 0)).reversed() .thenComparing(row -> getByIndex(row, 02)).reversed() .thenComparing(row -> getByIndex(row, 03)).reversed() .thenComparing(row -> getByIndex(row, 04)) .thenComparing(row -> getByIndex(row, 05)) .thenComparing(row -> getByIndex(row, 8)).reversed()); Collections.reverse(sortedByReverse); sortedByReverse.forEach(row -> log.info("先升序后Collections.reverse: {}", row)); /** * 方法四优缺点分析: * * 优点: * 1. 简单直观:先按一种规则排序,再整体反转,逻辑容易理解 * 2. 适合场景:当需要完全反转排序结果时非常方便 * 3. 易于调试:可以先验证正向排序是否正确,再考虑反转 * * 缺点: * 1. 逻辑错误:这是错误的实现方式!混合升序降序的排序规则不能简单反转 * 2. 结果错误:会导致排序结果完全不符合预期,所有列的排序方向都被反转 * 3. 性能浪费:额外的Collections.reverse操作增加了时间复杂度 * 4. 不适用场景:仅适用于全部升序要转为全部降序的简单场景 * 5. 维护陷阱:容易被误认为是优化的排序方式,实际上会产生错误结果 * * 注意:此方法演示了常见的排序错误,不要在实际代码中使用! */ // ============ 方法五:关键元组法(构建String元组,再倒序) ============ log.info("========== 集合排序:关键元组法(构建String元组,再倒序) =========="); List<String> sortedByTuple = new ArrayList<>(pureList); sortedByTuple.sort((row1, row2) -> { // 构建正向元组(未使用) String tuple1 = getByIndex(row1, 0) + "|" + getByIndex(row1, 02) + "|" + getByIndex(row1, 03) + "|" + getByIndex(row1, 04) + "|" + getByIndex(row1, 05) + "|" + getByIndex(row1, 8); String tuple2 = getByIndex(row2, 0) + "|" + getByIndex(row2, 02) + "|" + getByIndex(row2, 03) + "|" + getByIndex(row2, 04) + "|" + getByIndex(row2, 05) + "|" + getByIndex(row2, 8); // 构建反向元组(对需要降序的列进行反转) String reverseTuple1 = reverseValue(getByIndex(row1, 0)) + "|" + reverseValue(getByIndex(row1, 02)) + "|" + reverseValue(getByIndex(row1, 03)) + "|" + getByIndex(row1, 04) + "|" + getByIndex(row1, 05) + "|" + reverseValue(getByIndex(row1, 8)); String reverseTuple2 = reverseValue(getByIndex(row2, 0)) + "|" + reverseValue(getByIndex(row2, 02)) + "|" + reverseValue(getByIndex(row2, 03)) + "|" + getByIndex(row2, 04) + "|" + getByIndex(row2, 05) + "|" + reverseValue(getByIndex(row2, 8)); return reverseTuple1.compareTo(reverseTuple2); }); sortedByTuple.forEach(row -> log.info("关键元组法: {}", row)); /** * 方法五优缺点分析: * * 优点: * 1. 理论创新:通过字符串反转巧妙实现降序,思路独特 * 2. 一次比较:将多个列组合成一个字符串进行一次比较,减少多次函数调用 * 3. 可优化空间:可以预先计算和缓存元组,避免重复解析 * * 缺点: * 1. 性能开销:每次比较都需要构建两个元组字符串,包含多次字符串拼接和反转操作 * 2. 内存浪费:每个元组字符串都需要额外内存,大数据量时内存消耗严重 * 3. 字符串长度:元组字符串长度取决于列值长度,可能影响比较性能 * 4. 局限性强:只适用于字符串比较,数值类型需要额外的转换处理 * 5. 可读性差:通过字符串反转实现降序的逻辑不够直观,难以理解 * 6. 维护困难:如果列数或排序规则变化,需要修改元组构建逻辑 * 7. 错误风险:reverseValue函数对null值处理、特殊字符处理等需要额外考虑 */ // ============ 方法六:自定义Comparator静态方法封装 ============ log.info("========== 集合排序:自定义Comparator静态方法封装 =========="); List<String> sortedByCustomComparator = new ArrayList<>(pureList); sortedByCustomComparator.sort(SortUtils::multiColumnComparatorMixed); sortedByCustomComparator.forEach(row -> log.info("自定义Comparator封装: {}", row)); /** * 方法六优缺点分析: * * 优点: * 1. 职责分离:将排序逻辑从业务代码中分离,符合单一职责原则 * 2. 可测试性强:独立的静态方法便于单元测试和验证 * 3. 代码复用:Comparator可以在不同场景复用,提高代码复用性 * 4. 易于维护:排序逻辑集中在一个方法中,修改和维护更方便 * 5. 性能优化:可以在方法内部添加缓存机制,优化重复解析问题 * 6. 可读性好:方法名称明确表达排序意图,代码语义清晰 * 7. 扩展性强:可以通过参数配置不同的排序规则,提高灵活性 * * 缺点: * 1. 方法引用限制:使用方法引用时参数和返回值必须严格匹配Comparator接口 * 2. 调试复杂性:需要跳转到独立方法查看排序逻辑,调试时不够直观 * 3. 静态方法限制:无法访问实例变量,需要所有数据通过参数传递 * 4. 重复代码:与lambda方式相比,可能需要更多的样板代码 * 5. 方法数量:如果排序规则多样化,可能会产生多个Comparator方法 */ } /** * 多列混合排序Comparator * 排序规则:日期降序、列2降序、列3降序、列4升序、列5升序、列8降序 * * @param row1 第一行数据 * @param row2 第二行数据 * @return 比较结果,负数表示row1小于row2,0表示相等,正数表示row1大于row2 */ private static int multiColumnComparatorMixed(String row1, String row2) { int cmp; // 列0降序 cmp = getByIndex(row2, 0).compareTo(getByIndex(row1, 0)); if (cmp != 0) { return cmp; } // 列2降序 cmp = getByIndex(row2, 02).compareTo(getByIndex(row1, 02)); if (cmp != 0) { return cmp; } // 列3降序 cmp = getByIndex(row2, 03).compareTo(getByIndex(row1, 03)); if (cmp != 0) { return cmp; } // 列4升序 cmp = getByIndex(row1, 04).compareTo(getByIndex(row2, 04)); if (cmp != 0) { return cmp; } // 列5升序 cmp = getByIndex(row1, 05).compareTo(getByIndex(row2, 05)); if (cmp != 0) { return cmp; } // 列8降序 return getByIndex(row2, 8).compareTo(getByIndex(row1, 8)); } /** * 字符串反转方法,用于关键元组法实现降序排序 * 通过反转字符串来改变比较结果,实现降序效果 * * @param value 需要反转的字符串 * @return 反转后的字符串,如果输入为null则返回null */ private static String reverseValue(String value) { if (value == null) { return null; } return new StringBuilder(value).reverse().toString(); } }
http://www.cnnetsun.cn/news/4196004.html

相关文章:

  • 【C++ 面试真题】29. 聊聊 C++ 的线程管理(std::thread)
  • 单片机毕设项目:基于 STM32/51 单片机的4 通道无线病房呼叫液晶显示与语音报警系统设计 主从架构 NRF24L01 病床呼叫终端软硬件设计(020204)
  • 7个我自己常用的学习网站
  • 开源地理空间智能项目中的本体思想 4-2:影像篇——影像不进图谱,图谱给影像当索引
  • 【自适应滤波实战】归一化最小均方 (NLMS) 自适应噪声对消全解析:原理推导 + 数值实例 + Python 代码实现
  • c语言的纸币找零问题
  • 全球贸易进入“高关税时代”:企业必须重新学习如何做全球生意
  • DeepSeek Harness + GLM-5.3 超详细实战教程:我拼了套自己的AI 工位,还自己开发插件!
  • 扫描件加文本层:OCRmyPDF 离线使用完整指南
  • 溶血磷脂酰胆碱 (LPC):脂质代谢关键毒性分子,云克隆 ELISA 试剂盒助力脂质组与炎症损伤科研检测
  • 压电定位平台为什么要闭环?开环误差、传感器基准与Python测试
  • 大二学生用myBuilder两周搭出完整ERP,面试官直接让他演示了一遍
  • 如何获得更快更私密的浏览体验:开源浏览器 Thorium 完整指南
  • DeepSeek Harness 极简模式跑 Terminal Bench,模型基准测试实操
  • KeyboardChatterBlocker 实战教程:按键调阈值,修掉机械键盘连击
  • 【单片机课设毕设项目】基于 51/STM32 单片机的红外人体感应防盗报警环境监控系统设计 基于 51/STM32 单片机的 LCD1602 显示环境感知智能安防系统设计(017504)
  • Python Web后端框架FastAPI vs Flask
  • 网络安全等保合规文档整理
  • 【 C++ 】AVL树
  • 从ChatiSS九种体质舌面诊参数解码中医AI的Token底盘逻辑
  • 评价类模型
  • 2026深度测评10款降AI率工具红黑榜!优缺点全曝光,达标率对标顶级水准
  • MAA明日方舟自动化助手:新手 5 分钟跑通全流程,把重复劳动交给它
  • 单片机毕设项目:融合温光人体检测的 STM32 智能晾衣架设计与开发 本地显示 + 远程 APP 监控 STM32 智能晾衣架系统研究(017204)
  • 团队一体化协同平台怎么选?多款协作工具能力客观记录
  • SAP Gateway Foundation OData V4 工具全景解析,从服务发布、Metadata Cache 到 Payload Trace 的完整排障链路
  • 8.22【A】
  • 小米Kotlin专项面经:data class自动生成了什么、Kotlin空安全、Kotlin value class
  • 大语言模型在职业体育决策中的应用:从ChatGPT到AI协作工作流
  • Docker综合项目实验