• Java List排序 java ListMap 排序 Java listmap 模拟 oracle 排序 Java listmap 模拟 mysql 排序


            Java List排序 java ListMap 排序 Java listmap 模拟 oracle 排序 Java listmap 模拟 mysql 排序

    一、概述

            近期的开发工作中,遇到一个需求: 对 Listmap的结果集进行排序,类似于模拟 数据库中的Order By 排序。那么主要的需求有: 排序方式 ASC/DESC ; null 值处理:NULL FIRST / NULL LAST 。 在Java 中要实现以上相应的功能,对List进行排序,会遇到对应问题: 元素中有 null ,排序时候会抛出 NPE 、 null 元素放在 最前、最后面的问题。

            本文将基于Java8,逐一演示,上述中出现问题的对应示例代码;最终给出 List 排序的解决方案,实现易用性,通用性。

    二、问题

            1、元素有null,排序处理:

    1. /**
    2. * Description: null 值处理
    3. *
      1. null 元素,排序 NPE
    4. *
      2. 解决: null 放在最前面、最后面
    5. * @param
    6. * @return void
    7. * @version v1.0
    8. * @author wu
    9. * @date 2022/10/17 15:43
    10. */
    11. @Test
    12. public void nullListTest(){
    13. ArrayList list = Lists.newArrayList("22","33",null,"11");
    14. System.out.println("nullListTest 排序前:" + list);
    15. // list中有 null 元素,排序会抛出 NPE
    16. list.sort(Comparator.comparing(e->e)); // 抛出 NPE
    17. list.sort((e1,e2)->e1.compareTo(e2)); // 抛出 NPE
    18. // list.sort(Comparator.comparing(String::valueOf)); // 避免npe
    19. // null 值处理: null 放在最前
    20. list.sort(Comparator.comparing(e->e,Comparator.nullsFirst(String::compareTo)));
    21. System.out.println("nullListTest 排序后: null 放在最前:" + list);
    22. // null 值处理: null 放在最后
    23. list.sort(Comparator.comparing(e->e,Comparator.nullsLast(String::compareTo)));
    24. System.out.println("nullListTest 排序后:null 放在最后:" + list);
    25. }

            1.1、输出结果:

    1. nullListTest 排序前:[22, 33, null, 11]
    2. java.lang.NullPointerException
    3. ...

            2、倒序 DESC时,null 值放在 最前面、最后面的处理

    1. /**
    2. * Description: 倒序的时候, null 值处理
    3. *
      1. null 最前面: nullsLast 方法
    4. *
      2. null 最后面: nullsFirst 方法
    5. * @return void
    6. * @version v1.0
    7. * @author wu
    8. * @date 2022/10/17 16:37
    9. */
    10. @Test
    11. public void nullDESCTest() throws Exception{
    12. ArrayList list = Lists.newArrayList("22","33",null,"11");
    13. System.out.println("nullDESCTest 排序前:" + list);
    14. // DESC , null first
    15. // list.sort(Comparator.comparing((String e)->e,Comparator.nullsFirst(String::compareTo)).reversed());
    16. list.sort(Comparator.comparing((String e)->e,Comparator.nullsLast(String::compareTo)).reversed());
    17. System.out.println("nullDESCTest DESC , null first :" + list);
    18. // DESC , null last
    19. list.sort(Comparator.comparing((String e)->e,Comparator.nullsFirst(String::compareTo)).reversed());
    20. System.out.println("nullDESCTest DESC , null last :" + list);
    21. }

            2.1、输出结果:

    1. nullDESCTest 排序前:[22, 33, null, 11]
    2. nullDESCTest DESC , null first :[null, 33, 22, 11]
    3. nullDESCTest DESC , null last :[33, 22, 11, null]

            3、数字是字符串类型时,排序不对的问题:

    1. /**
    2. * Description: 字符串类型数字 排序
    3. *
      解决:字符串转换为数字,进行排序
    4. * @return void
    5. * @version v1.0
    6. * @author wu
    7. * @date 2022/10/17 15:44
    8. */
    9. @Test
    10. public void strNumTest() throws Exception{
    11. List list = Lists.newArrayList("10","11","101","111");
    12. System.out.println("strNumTest 排序前:" + list);
    13. // 倒序排序
    14. list.sort(Comparator.comparing(String::valueOf).reversed());
    15. // list.sort(Comparator.comparing((String e)->Integer.valueOf(e)).reversed()); // 解决排序不对的问题
    16. System.out.println("strNumTest 排序后:" + list);
    17. }

            3.1、输出结果是:

    1. strNumTest 排序前:[10, 11, 101, 111]
    2. strNumTest 排序后:[111, 11, 101, 10]

    三、解决 --- 通用排序方案

            1、上述代码中,演示了可能出现的问题,以及对应的解决方案:

    • 元素中有null , 使用 Comparator.nullsFirst / Comparator.nullsLast
    • 倒序时null元素 处理: 最前面 --- Comparator.nullsLast ; 最后面 --- Comparator.nullsFirst
    • 数字是字符串类型时: 转换为数字进行排序

            2、List> 排序可能遇到问题:

    • 排序字段不确定
    • 排序字段类型不确定
    • 排序方式不确定
    • 可能 出现null元素

            3、经整理汇总后,通用排序流程如下:

            4、定义一个 ListMapConfig 配置类 ,统一维护相关的配置:

    1. /**
    2. * Description: List Map 排序 配置
    3. * @author w
    4. * @version 1.0
    5. * @date 2022/10/17 16:09
    6. */
    7. public class ListMapConfig {
    8. private String orderProperty ; // 排序字段:
    9. private String porpertyType = "STRING"; // 属性类型: STRING / NUMBER
    10. private String orderMode ="ASC"; // 排序方式: ASC/DESC
    11. private String orderModeNull ="LAST"; // null值处理: FIRST / LAST
    12. public static ListMapConfig getDefault(){
    13. return new ListMapConfig();
    14. }
    15. // ignore getter / setter
    16. }

            5、通用的 ListMap排序方法:

    1. public static void processSort(List> listMap , ListMapConfig config){
    2. String orderProperty = config.getOrderProperty();
    3. Assert.isTrue(StringUtils.isNotBlank(orderProperty));
    4. if("NUMBER".equals(config.getPorpertyType())){
    5. // 数字 类型排序
    6. if("DESC".equals(config.getOrderMode())){
    7. if("FIRST".equals(config.getOrderModeNull())){
    8. listMap.sort(Comparator.comparing((Map e)->{
    9. Object val = e.get(orderProperty);
    10. return val == null ? null : Double.valueOf(val.toString());
    11. // 倒序时,null值放在最后,反过来:需要用 nullsLast
    12. },Comparator.nullsLast(Double::compareTo)).reversed());
    13. }else {
    14. listMap.sort(Comparator.comparing((Map e)->{
    15. Object val = e.get(orderProperty);
    16. return val == null ? null : Double.valueOf(val.toString());
    17. // 倒序时,null值放在最后,反过来:需要用 nullsFirst
    18. },Comparator.nullsFirst(Double::compareTo)).reversed());
    19. }
    20. }else {
    21. if("FIRST".equals(config.getOrderModeNull())){
    22. listMap.sort(Comparator.comparing((Map e)->{
    23. Object val = e.get(orderProperty);
    24. return val == null ? null : Double.valueOf(val.toString());
    25. },Comparator.nullsFirst(Double::compareTo)));
    26. }else {
    27. listMap.sort(Comparator.comparing((Map e)->{
    28. Object val = e.get(orderProperty);
    29. return val == null ? null : Double.valueOf(val.toString());
    30. },Comparator.nullsFirst(Double::compareTo)));
    31. }
    32. }
    33. }else if("STRING".equals(config.getPorpertyType())){
    34. // 字符串 类型排序
    35. if("DESC".equals(config.getOrderMode())){
    36. if("FIRST".equals(config.getOrderModeNull())){
    37. listMap.sort(Comparator.comparing((Map e) -> {
    38. Object val = e.get(orderProperty);
    39. return null == val ? null : val.toString();
    40. // 倒序时,null值放在最后,反过来:需要用 nullsLast
    41. },Comparator.nullsLast(String::compareTo)).reversed());
    42. }else {
    43. listMap.sort(Comparator.comparing((Map e) -> {
    44. Object val = e.get(orderProperty);
    45. return null == val ? null : val.toString();
    46. // 倒序时,null值放在最后,反过来:需要用 nullsFirst
    47. },Comparator.nullsFirst(String::compareTo)).reversed());
    48. }
    49. }else {
    50. if("FIRST".equals(config.getOrderModeNull())){
    51. listMap.sort(Comparator.comparing((Map e) -> {
    52. Object val = e.get(orderProperty);
    53. return null == val ? null : val.toString();
    54. },Comparator.nullsFirst(String::compareTo)));
    55. }else {
    56. listMap.sort(Comparator.comparing((Map e) -> {
    57. Object val = e.get(orderProperty);
    58. return null == val ? null : val.toString();
    59. },Comparator.nullsLast(String::compareTo)));
    60. }
    61. }
    62. }
    63. }

    四、代码测试

            1、创建一个 ListMapSortTest2 测试类:

    1. public class ListMapSortTest2 {
    2. static List orderList = null;
    3. static List> listMap = null;
    4. public static void main(String[] args) {
    5. init();
    6. System.out.println(orderList);
    7. // 1、转换为map
    8. listMap = com.google.common.collect.Lists.newArrayList();
    9. for (Order e : orderList) {
    10. JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(e));
    11. Map map = JSON.toJavaObject(jsonObject, Map.class);
    12. listMap.add(map);
    13. }
    14. System.out.println("listMap :"+listMap);
    15. ListMapConfig config = ListMapConfig.getDefault();
    16. config.setOrderProperty("appNo");
    17. // STRING-TEST1: ASC - NULL FIRST
    18. config.setOrderModeNull("FIRST");
    19. processSort(listMap,config);
    20. System.out.println("STRING-TEST1: ASC - NULL FIRST : " + listMap);
    21. // STRING-TEST2: ASC - NULL LAST
    22. config.setOrderModeNull("LAST");
    23. processSort(listMap,config);
    24. System.out.println("STRING-TEST2: ASC - NULL LAST : " + listMap);
    25. // STRING-TEST3: DESC - NULL FIRST
    26. config.setOrderModeNull("FIRST");
    27. config.setOrderMode("DESC");
    28. processSort(listMap,config);
    29. System.out.println("STRING-TEST3: DESC - NULL FIRST : " + listMap);
    30. // STRING-TEST4: DESC - NULL LAST
    31. config.setOrderModeNull("LAST");
    32. config.setOrderMode("DESC");
    33. processSort(listMap,config);
    34. System.out.println("STRING-TEST4: DESC - NULL LAST : " + listMap);
    35. }
    36. private static void init() {
    37. orderList = Lists.newArrayList();
    38. orderList.add(new Order(1,"小明","203"));
    39. orderList.add(new Order(2,"小红",null));
    40. orderList.add(new Order(3,"小刚","404"));
    41. }
    42. static class Order {
    43. private Integer id;
    44. private String name;
    45. private String appNo;
    46. public Order(Integer id, String name, String appNo) {
    47. this.id = id;
    48. this.name = name;
    49. this.appNo = appNo;
    50. }
    51. public Order() {
    52. }
    53. public Integer getId() {
    54. return id;
    55. }
    56. public void setId(Integer id) {
    57. this.id = id;
    58. }
    59. public String getName() {
    60. return name;
    61. }
    62. public void setName(String name) {
    63. this.name = name;
    64. }
    65. public String getAppNo() {
    66. return appNo;
    67. }
    68. public void setAppNo(String appNo) {
    69. this.appNo = appNo;
    70. }
    71. @Override
    72. public String toString() {
    73. return "Order{" +
    74. "id=" + id +
    75. ", name='" + name + '\'' +
    76. ", appNo='" + appNo + '\'' +
    77. '}';
    78. }
    79. }
    80. }

            3、注意:Number类型,未测试!

    五、总结

            1、本文初步解决 List 集合的排序问题,因 map集合中元素类型的不确定性,所以 当前写了2种排序方式:统一按照字符串排序 或者 数字类型 ; 在 ListMapConfig.porpertyType 中,可以添加 相应的其他类型,进行功能扩展 。 比如: java.util.Date 类型处理。

            2、ListMapConfig 类中,porpertyType 等属性,可以定义为 枚举类型, 便于更好的理解,和后续扩展。

            3、通用排序方法:processSort , 写了太多的 if else , 可以引入设计模式,更加优雅!

    排序相关的文章资料参考:

     

    使用MySQL FIELD函数实现自定义排序 特定字段排序 指定字段排序_HaHa_Sir的博客-CSDN博客

    Java List集合排序 Java8 List集合排序方法 Java Lambda集合排序_HaHa_Sir的博客-CSDN博客_java8 集合排序 

    Oracle 中文排序 Oracle 中文字段排序_HaHa_Sir的博客-CSDN博客_oracle 中文排序

  • 相关阅读:
    Mybatis-plus 使用
    高速电路设计笔记----第二章
    2024 证券从业资格证考试备考资料分享
    速查!PMP考试成绩已出!
    嵌入式linux系统中面试过程经验分享
    docker 安装 neo4j
    [项目管理-6]:软硬件项目管理 - 项目沟通管理(渠道、方法)
    Java项目:SSM校园班级同学通讯录管理系统
    Flume环境搭建
    tf-vsn网络
  • 原文地址:https://blog.csdn.net/HaHa_Sir/article/details/127629841