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

本文介绍如何解决Java中List<Map>集合的排序问题,包括处理null值、倒序排序及不同数据类型排序的方法,并提供了一个通用排序方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        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<Map> 排序的解决方案,实现易用性,通用性。

二、问题

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

/**
     * Description: null 值处理
     * <br> 1. null 元素,排序 NPE
     * <br> 2. 解决: null 放在最前面、最后面
     * @param
     * @return void
     * @version v1.0
     * @author wu
     * @date 2022/10/17 15:43
     */
    @Test
    public void nullListTest(){
        ArrayList<String> list = Lists.newArrayList("22","33",null,"11");
         System.out.println("nullListTest  排序前:" + list);
        // list中有 null 元素,排序会抛出 NPE
        list.sort(Comparator.comparing(e->e)); // 抛出 NPE
        list.sort((e1,e2)->e1.compareTo(e2)); // 抛出 NPE
//        list.sort(Comparator.comparing(String::valueOf)); // 避免npe

        // null 值处理: null 放在最前
        list.sort(Comparator.comparing(e->e,Comparator.nullsFirst(String::compareTo)));
        System.out.println("nullListTest  排序后: null 放在最前:" + list);

        // null 值处理: null 放在最后
        list.sort(Comparator.comparing(e->e,Comparator.nullsLast(String::compareTo)));
        System.out.println("nullListTest  排序后:null 放在最后:" + list);
    }

        1.1、输出结果:

nullListTest  排序前:[22, 33, null, 11]

java.lang.NullPointerException 
...

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

/**
     * Description: 倒序的时候, null 值处理
     * <br> 1. null 最前面: nullsLast 方法
     * <br> 2. null 最后面: nullsFirst 方法
     * @return void
     * @version v1.0
     * @author wu
     * @date 2022/10/17 16:37
     */
    @Test
    public void nullDESCTest() throws Exception{
        ArrayList<String> list = Lists.newArrayList("22","33",null,"11");
        System.out.println("nullDESCTest  排序前:" + list);

        // DESC ,  null  first
//        list.sort(Comparator.comparing((String e)->e,Comparator.nullsFirst(String::compareTo)).reversed());
        list.sort(Comparator.comparing((String e)->e,Comparator.nullsLast(String::compareTo)).reversed());
        System.out.println("nullDESCTest  DESC ,  null  first :" + list);

        // DESC ,  null  last
        list.sort(Comparator.comparing((String e)->e,Comparator.nullsFirst(String::compareTo)).reversed());
        System.out.println("nullDESCTest  DESC ,  null  last :" + list);

    }

        2.1、输出结果:

nullDESCTest  排序前:[22, 33, null, 11]
nullDESCTest  DESC ,  null  first :[null, 33, 22, 11]
nullDESCTest  DESC ,  null  last :[33, 22, 11, null]

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

  /**
     * Description: 字符串类型数字 排序
     * <br> 解决:字符串转换为数字,进行排序
     * @return void
     * @version v1.0
     * @author wu
     * @date 2022/10/17 15:44
     */
    @Test
    public void strNumTest() throws Exception{
        List<String> list = Lists.newArrayList("10","11","101","111");
        System.out.println("strNumTest  排序前:" + list);

        // 倒序排序
        list.sort(Comparator.comparing(String::valueOf).reversed());
//        list.sort(Comparator.comparing((String e)->Integer.valueOf(e)).reversed()); // 解决排序不对的问题
        System.out.println("strNumTest  排序后:" + list);

    }
    

        3.1、输出结果是:

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

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

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

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

        2、List<Map<String,Object>> 排序可能遇到问题:

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

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

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

/**
 * Description: List Map 排序 配置
 * @author w
 * @version 1.0
 * @date 2022/10/17 16:09
 */
public class ListMapConfig {

    private String orderProperty ; // 排序字段:
    private String porpertyType = "STRING"; // 属性类型: STRING / NUMBER
    private String orderMode ="ASC"; // 排序方式: ASC/DESC
    private String orderModeNull ="LAST"; // null值处理: FIRST / LAST
    
    public static ListMapConfig getDefault(){
        return new ListMapConfig();
    }
    // ignore getter / setter     
}

        5、通用的 ListMap排序方法:

public static void processSort(List<Map<String, Object>> listMap , ListMapConfig config){
    String orderProperty = config.getOrderProperty();
    Assert.isTrue(StringUtils.isNotBlank(orderProperty));

    if("NUMBER".equals(config.getPorpertyType())){
        // 数字 类型排序
        if("DESC".equals(config.getOrderMode())){
            if("FIRST".equals(config.getOrderModeNull())){
                listMap.sort(Comparator.comparing((Map e)->{
                    Object val = e.get(orderProperty);
                    return val == null ? null : Double.valueOf(val.toString());
                    // 倒序时,null值放在最后,反过来:需要用 nullsLast
                },Comparator.nullsLast(Double::compareTo)).reversed());
            }else {
                listMap.sort(Comparator.comparing((Map e)->{
                    Object val = e.get(orderProperty);
                    return val == null ? null : Double.valueOf(val.toString());
                    // 倒序时,null值放在最后,反过来:需要用 nullsFirst
                },Comparator.nullsFirst(Double::compareTo)).reversed());
            }
        }else {
            if("FIRST".equals(config.getOrderModeNull())){
                listMap.sort(Comparator.comparing((Map e)->{
                    Object val = e.get(orderProperty);
                    return val == null ? null : Double.valueOf(val.toString());
                },Comparator.nullsFirst(Double::compareTo)));
            }else {
                listMap.sort(Comparator.comparing((Map e)->{
                    Object val = e.get(orderProperty);
                    return val == null ? null : Double.valueOf(val.toString());
                },Comparator.nullsFirst(Double::compareTo)));
            }
        }
    }else if("STRING".equals(config.getPorpertyType())){
        // 字符串 类型排序
        if("DESC".equals(config.getOrderMode())){
            if("FIRST".equals(config.getOrderModeNull())){
                listMap.sort(Comparator.comparing((Map e) -> {
                    Object val =  e.get(orderProperty);
                    return null == val ? null : val.toString();
                    // 倒序时,null值放在最后,反过来:需要用 nullsLast
                },Comparator.nullsLast(String::compareTo)).reversed());
            }else {
                listMap.sort(Comparator.comparing((Map e) -> {
                    Object val =  e.get(orderProperty);
                    return null == val ? null : val.toString();
                    // 倒序时,null值放在最后,反过来:需要用 nullsFirst
                },Comparator.nullsFirst(String::compareTo)).reversed());
            }
        }else {
            if("FIRST".equals(config.getOrderModeNull())){
                listMap.sort(Comparator.comparing((Map e) -> {
                    Object val =  e.get(orderProperty);
                    return null == val ? null : val.toString();
                },Comparator.nullsFirst(String::compareTo)));
            }else {
                listMap.sort(Comparator.comparing((Map e) -> {
                    Object val =  e.get(orderProperty);
                    return null == val ? null : val.toString();
                },Comparator.nullsLast(String::compareTo)));
            }
        }
    }
}

四、代码测试

        1、创建一个 ListMapSortTest2 测试类:

public class ListMapSortTest2 {

  static   List<Order> orderList =  null;
  static  List<Map<String,Object>> listMap = null;

    public static void main(String[] args) {
        init();
        System.out.println(orderList);

        // 1、转换为map
        listMap = com.google.common.collect.Lists.newArrayList();
        for (Order e : orderList) {
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(e));
            Map map = JSON.toJavaObject(jsonObject, Map.class);
            listMap.add(map);
        }
        System.out.println("listMap :"+listMap);

        ListMapConfig config = ListMapConfig.getDefault();
        config.setOrderProperty("appNo");

        // STRING-TEST1: ASC - NULL FIRST
        config.setOrderModeNull("FIRST");
        processSort(listMap,config);
        System.out.println("STRING-TEST1: ASC - NULL FIRST : " + listMap);

        // STRING-TEST2: ASC - NULL LAST
        config.setOrderModeNull("LAST");
        processSort(listMap,config);
        System.out.println("STRING-TEST2: ASC - NULL LAST : " + listMap);

        // STRING-TEST3: DESC - NULL FIRST
        config.setOrderModeNull("FIRST");
        config.setOrderMode("DESC");
        processSort(listMap,config);
        System.out.println("STRING-TEST3: DESC - NULL FIRST : " + listMap);

        // STRING-TEST4: DESC - NULL LAST
        config.setOrderModeNull("LAST");
        config.setOrderMode("DESC");
        processSort(listMap,config);
        System.out.println("STRING-TEST4: DESC - NULL LAST : " + listMap);

    }

    private static void init() {
        orderList = Lists.newArrayList();
        orderList.add(new Order(1,"小明","203"));
        orderList.add(new Order(2,"小红",null));
        orderList.add(new Order(3,"小刚","404"));
    }
    
    static class Order {
        private Integer id;
        private String name;
        private String appNo;

        public Order(Integer id, String name, String appNo) {
            this.id = id;
            this.name = name;
            this.appNo = appNo;
        }
    
        public Order() {
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAppNo() {
            return appNo;
        }
    
        public void setAppNo(String appNo) {
            this.appNo = appNo;
        }
    
        @Override
        public String toString() {
            return "Order{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", appNo='" + appNo + '\'' +
                    '}';
        }
    }
}

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

五、总结

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

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

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

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

 

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

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

Oracle 中文排序 Oracle 中文字段排序_HaHa_Sir的博客-优快云博客_oracle 中文排序

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值