Java对List Object按照对象属性进行自定义排序

博客指出对比两个查询结果排序时,若数据次序不一致,主要因SQL中存在Order By语句,可去除或让两个列表同时添加一致的Order By语句。还提及Java Comparator接口compare方法决定排序升降序,以及Collections.sort()排序详解。

 注意:如果需要对比两个查询结果的排序,假如数据次序不一致如:List1<->List2 ;             主要原因是SQL中存在 Order By 语句,去除掉或者List1;List2同时添加一致 的 Order By语句即可。

public class ListSortUtils {
    /**
     * 对list的元素按照多个属性名称排序
     *
     * @param list
     * @param isAsc true升序,false降序
     * @param sortnameArr 参数数组
     * @param <E>
     */
    public static <E> void sort(List<E> list, final boolean isAsc, final String... sortnameArr) {
        Collections.sort(list, new Comparator<E>() {
            public int compare(E a, E b) {
                int ret = 0;
                try {
                    for (int i = 0; i < sortnameArr.length; i++) {
                        ret = ListSortUtils.compareObject(sortnameArr[i], isAsc, a, b);
                        if (0 != ret) {
                            break;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return ret;
            }
        });
    }

    /**
     * 给list的每个属性都指定是升序还是降序
     *
     * @param list
     * @param sortnameArr 参数数组
     * @param typeArr     每个属性对应的升降序数组, true升序,false降序
     * @param <E>
     */
    public static <E> void sort(List<E> list, final String[] sortnameArr, final boolean[] typeArr) {
        if (sortnameArr.length != typeArr.length) {
            throw new RuntimeException("属性数组元素个数和升降序数组元素个数不相等");
        }
        Collections.sort(list, new Comparator<E>() {

            public int compare(E a, E b) {
                int ret = 0;
                try {
                    for (int i = 0; i < sortnameArr.length; i++) {
                        ret = ListSortUtils.compareObject(sortnameArr[i], typeArr[i], a, b);
                        if (0 != ret) {
                            break;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return ret;
            }
        });
    }

    /**
     * 对2个对象按照指定属性名称进行排序
     * @param sortname 属性名称
     * @param isAsc true升序,false降序
     * @param a
     * @param b
     * @param <E>
     * @return
     * @throws Exception
     */
    private static <E> int compareObject(final String sortname, final boolean isAsc, E a, E b) throws Exception {
        if(sortname == null){
            return 0;
        }
        int ret;
        Object value1 = ListSortUtils.forceGetFieldValue(a, sortname);
        Object value2 = ListSortUtils.forceGetFieldValue(b, sortname);
        if(value1 == null || value2 == null){
            return 0;
        }
        String str1 = value1.toString();
        String str2 = value2.toString();
        if (value1 instanceof Number && value2 instanceof Number) {
            int maxlen = Math.max(str1.length(), str2.length());
            str1 = ListSortUtils.addZero2Str((Number) value1, maxlen);
            str2 = ListSortUtils.addZero2Str((Number) value2, maxlen);
        } else if (value1 instanceof Date && value2 instanceof Date) {
            long time1 = ((Date) value1).getTime();
            long time2 = ((Date) value2).getTime();
            int maxlen = Long.toString(Math.max(time1, time2)).length();
            str1 = ListSortUtils.addZero2Str(time1, maxlen);
            str2 = ListSortUtils.addZero2Str(time2, maxlen);
        }
        /**
     * 升序排的话就是第一个参数.compareTo(第二个参数);
     * 降序排的话就是第二个参数.compareTo(第一个参数);
         * compare方法决定排序的升序降序问题 
         * (https://blog.youkuaiyun.com/qq_28863045/article/details/79967749)
     */  
        if (isAsc) {
            ret = str1.compareTo(str2);
        } else {
            ret = str2.compareTo(str1);
        }
        return ret;
    }

    /**
     * 给数字对象按照指定长度在左侧补0
     * 使用案例: addZero2Str(11,4) 返回 "0011", addZero2Str(-18,6)返回 "-000018"
     *
     * @param numObj
     * @param length
     * @return
     */
    public static String addZero2Str(Number numObj, int length) {
        NumberFormat nf = NumberFormat.getInstance();
        // 设置是否使用分组
        nf.setGroupingUsed(false);
        // 设置最大整数位数
        nf.setMaximumIntegerDigits(length);
        // 设置最小整数位数
        nf.setMinimumIntegerDigits(length);
        return nf.format(numObj);
    }

    /**
     * 获取指定对象的指定属性值(去除private,protected的限制)
     *
     * @param obj  属性名称所在的对象
     * @param fieldName 属性名称
     * @return
     * @throws Exception
     */
    public static Object forceGetFieldValue(Object obj, String fieldName) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        Object object = null;
        boolean accessible = field.isAccessible();
        if (!accessible) {
            // 如果是private,protected修饰的属性,需要修改为可以访问的
            field.setAccessible(true);
            object = field.get(obj);
            // 还原private,protected属性的访问性质
            field.setAccessible(accessible);
            return object;
        }
        object = field.get(obj);
        return object;
    }

}

参考:java Comparator接口中(底层源码)compare方法决定排序的升序降序问题

          Java中Collections.sort()排序详解

写法举例:

String [] sortName = {"属性1","属性2",......};
//排序:true->代表升序;false ->代表降序
boolean [] isAscArr = {true,false,......};
ListSortUtils.sort(list,sortName,isAscArr);

 测试代码:

public static void main(String[] args) {
    Dept dept1=new Dept();
    dept1.setLevel(1);
    dept1.setCode("1");
    dept1.setOrderId(4);
    dept1.setName("一号");
    Dept dept2=new Dept();
    dept2.setLevel(1);
    dept2.setCode("2");
    dept2.setOrderId(3);
    dept2.setName("二号");
    Dept dept3=new Dept();
    dept3.setLevel(1);
    dept3.setCode("3");
    dept3.setOrderId(2);
    dept3.setName("三号");
    Dept dept4=new Dept();
    dept4.setLevel(1);
    dept4.setCode("4");
    dept4.setOrderId(1);
    dept4.setName("四号");

    List<Dept> list=new ArrayList<>();
    list.add(dept1);
    list.add(dept2);
    list.add(dept3);
    list.add(dept4);

    for (Dept dept:list){
         System.out.println("level="+dept.getLevel()+"      code="+dept.getCode()+"      orderId="+dept.getOrderId()+"      name="+dept.getName());
    }

    System.out.println("#################################################################################");
    String [] sortNameArrSHWQ = {"level","code","orderId"};
    //排序:true->代表升序;false ->代表降序
    boolean [] isAscArrSHWQ = {true,true,true};
    ListSortUtils.sort(list,sortNameArrSHWQ,isAscArrSHWQ);

    for (Dept dept:list){
        System.out.println("level="+dept.getLevel()+"      code="+dept.getCode()+"      orderId="+dept.getOrderId()+"      name="+dept.getName());
    }

 

<think> 我们参考了用户提供的多个引用,这些引用展示了在Java中对List进行自定义排序的不同方法,特别是针对List<Map>或List<自定义对象>的情况。用户的需求是“对List<Map>对象数组进行自定义排序的实现方法”。下面我们将结合引用内容,给出几种常见的实现方式。 根据引用[1],我们可以使用`Collections.sort`或List的`sort`方法,并传入自定义的`Comparator`。对于List<Map>,我们可以按照Map中某个键的值进行排序。 引用[3]展示了使用Java 8 Stream进行排序的方法,特别是对List<Map>按照某个字段(如"Createtime")进行排序。 引用[4]则介绍了如何对多个动态属性字段进行排序,可以动态指定升序或降序。 下面我们分别介绍几种方法: ### 方法1:使用匿名内部类(传统方式) ```java List<Map<String, Object>> list = new ArrayList<>(); // 假设已经填充了数据 // 按照Map中的"count"字段降序排序 list.sort(new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) { // 假设count是Integer类型 Integer count1 = (Integer) o1.get("count"); Integer count2 = (Integer) o2.get("count"); // 降序排序 return count2.compareTo(count1); } }); ``` ### 方法2:使用Lambda表达式(Java 8及以上) ```java // 按照Map中的"count"字段升序排序 list.sort((o1, o2) -> { Integer count1 = (Integer) o1.get("count"); Integer count2 = (Integer) o2.get("count"); return count1.compareTo(count2); }); ``` ### 方法3:使用Comparator.comparing(更简洁的方式) ```java // 升序排序 list.sort(Comparator.comparing(m -> (Integer) m.get("count"))); // 降序排序 list.sort(Comparator.comparing((Map<String, Object> m) -> (Integer) m.get("count")).reversed()); ``` ### 方法4:多个字段动态排序(引用[4]的方法) 假设我们有一个动态的属性列表和对应的排序顺序(升序或降序),我们可以构建一个链式的Comparator。 ```java // 假设我们有如下动态排序条件 List<String> sortProperties = Arrays.asList("count", "name"); // 先按count排序,再按name排序 List<Boolean> sortOrders = Arrays.asList(true, false); // true表示降序,false表示升序 // 构建Comparator Comparator<Map<String, Object>> comparator = null; for (int i = 0; i < sortProperties.size(); i++) { String property = sortProperties.get(i); boolean isDesc = sortOrders.get(i); Comparator<Map<String, Object>> currentComparator = Comparator.comparing(m -> { Object value = m.get(property); // 这里需要根据实际类型处理,假设都是Comparable return (Comparable) value; }); if (isDesc) { currentComparator = currentComparator.reversed(); } if (comparator == null) { comparator = currentComparator; } else { comparator = comparator.thenComparing(currentComparator); } } // 使用这个comparator进行排序 if (comparator != null) { list.sort(comparator); } ``` ### 注意事项 1. 在比较时,需要确保Map中的键存在,且对应的值可以比较。如果值可能是null,需要做null处理。 2. 类型转换:从Map中取出的值是Object类型,需要根据实际情况转换为具体的可比较类型(如Integer、String等)。 3. 如果字段值可能是不同的类型(比如有的Map中count是Integer,有的是String),则需要额外处理。 ### 示例:处理可能的null值和不同类型 ```java list.sort((o1, o2) -> { Object value1 = o1.get("count"); Object value2 = o2.get("count"); // 处理null值:将null视为最小 if (value1 == null && value2 == null) return 0; if (value1 == null) return -1; // 升序时null排前面,降序则可能需要调整 if (value2 == null) return 1; // 确保它们是可比较的,比如都是Integer if (value1 instanceof Integer && value2 instanceof Integer) { return Integer.compare((Integer) value1, (Integer) value2); } else { // 如果类型不同,可以转换为字符串比较,或者抛出异常等 return value1.toString().compareTo(value2.toString()); } }); ``` ### 总结 以上提供了多种对List<Map>进行自定义排序的方法,从传统的匿名内部类到Java 8的Stream和Lambda表达式,以及动态多字段排序。用户可以根据自己的Java版本和具体需求选择合适的方法。 §§相关问题§§ 1. Java中如何对List<自定义对象>进行排序? 2. 在Java 8中,如何使用Stream对List进行多字段排序? 3. 在排序时如何处理null值? 4. Java的Comparator.comparing方法如何使用? </think> 在 Java 中对 `List<Map>` 进行自定义排序,可以通过以下方法实现(基于 Java 8+ 的 Stream API 和 Lambda 表达式): ### 1. 单字段排序(按指定键的值排序) ```java List<Map<String, Object>> list = new ArrayList<>(); // 待排序列表 // 按 "age" 字段升序排序 List<Map<String, Object>> sortedList = list.stream() .sorted(Comparator.comparing(m -> (Integer) m.get("age"))) .collect(Collectors.toList()); // 按 "salary" 字段降序排序 List<Map<String, Object>> sortedList = list.stream() .sorted(Comparator.comparing(m -> (Double) m.get("salary")).reversed()) .collect(Collectors.toList()); ``` ### 2. 多字段组合排序(优先级排序) ```java // 先按 "department" 升序,再按 "salary" 降序 List<Map<String, Object>> sortedList = list.stream() .sorted(Comparator .comparing(m -> (String) m.get("department")) .thenComparing(Comparator.comparing(m -> (Double) m.get("salary")).reversed()) ) .collect(Collectors.toList()); ``` ### 3. 动态字段排序(支持字段名和顺序动态传入) ```java // 定义排序规则:字段名列表 + 排序方向 List<String> sortFields = Arrays.asList("department", "age"); List<Boolean> ascendingFlags = Arrays.asList(true, false); // true=升序, false=降序 Comparator<Map<String, Object>> comparator = null; for (int i = 0; i < sortFields.size(); i++) { String field = sortFields.get(i); Comparator<Map<String, Object>> current = Comparator.comparing(m -> (Comparable) m.get(field) ); if (!ascendingFlags.get(i)) current = current.reversed(); comparator = (comparator == null) ? current : comparator.thenComparing(current); } List<Map<String, Object>> sortedList = list.stream() .sorted(comparator) .collect(Collectors.toList()); ``` ### 4. 传统 Comparator 实现(兼容 Java 7) ```java list.sort(new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) { // 按 "name" 字段升序 String name1 = (String) o1.get("name"); String name2 = (String) o2.get("name"); return name1.compareTo(name2); } }); ``` ### 关键注意事项 1. **类型转换**: 从 `Map` 获取值后需显式转换为实际类型(如 `(Integer) map.get("age")`) 2. **空值处理**: 建议使用 `Objects.compare()` 处理 `null` 值: ```java .sorted(Comparator.comparing(m -> (String) m.get("department"), Comparator.nullsLast(Comparator.naturalOrder()) )) ``` 3. **性能考虑**: 大数据量时使用 `parallelStream()` 并行排序 ### 示例场景 ```java List<Map<String, Object>> employees = new ArrayList<>(); employees.add(Map.of("name", "Alice", "age", 28, "dept", "HR")); employees.add(Map.of("name", "Bob", "age", 32, "dept", "IT")); // 按部门升序+年龄降序 List<Map<String, Object>> sorted = employees.stream() .sorted(Comparator .comparing(m -> (String) m.get("dept")) .thenComparing(Comparator.comparing(m -> (Integer) m.get("age")).reversed()) ) .collect(Collectors.toList()); ``` > 引用说明:以上实现参考了 Java 的 `Comparator` 接口设计[^1],结合了 Stream API 的链式排序能力[^2][^3],并支持动态字段配置[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值