Lambda表达式对List对象实现多个动态属性排序

一、 Lambda表达式对List对象实现多个动态属性排序

java 复制代码
package com.example.gateway;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author wux
 * @version 1.0.0
 * @description lambda表达式对List对象实现多个动态属性排序
 * 场景一:javaObject集合转JSONObject集合,动态指定多个要排序的字段
 * 场景二:javaObject集合, 动态指定多个要排序的字段
 * 场景三:JSONObject集合, 动态指定多个要排序的字段
 * @date 2024/11/29 10:25
 */
public class Test2 {
    public static void main(String[] args) throws Exception {

        System.out.println("=============场景一:javaObject集合转JSONObject集合,动态指定多个要排序的字段===============");
        javaObjectToJsonObjectList().stream().forEach(System.out::println);

        System.out.println("==============场景二:javaObject集合, 动态指定多个要排序的字段==============");
        javaObjectList().stream().forEach(System.out::println);

        System.out.println("==============场景三:JSONObject集合, 动态指定多个要排序的字段==============");
        jsonObjects().stream().forEach(System.out::println);
    }

    private static List<WxObj> javaObjectList() throws NoSuchMethodException {
        WxObj a = new WxObj("w",10.00,20.00,10.00,20.00,10.00);
        WxObj b = new WxObj("w",10.00,20.00,12.00,20.00,10.00);
        WxObj c = new WxObj("w",12.00,10.00,10.00,20.00,10.00);
        WxObj d = new WxObj("w",12.00,20.00,10.00,20.00,10.00);
        List<WxObj> list = new ArrayList<WxObj>();
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);

        List<String> sortProperties = new ArrayList<>();
        //动态指定要排序的属性字段
        //此处可以根据业务需要传具体字段,此处测试就先写死
        sortProperties.add("ys1");
        sortProperties.add("ys2");
        sortProperties.add("ys3");
        Map<String, Boolean> sortOrders = new HashMap<>();
        //动态指定属性字段对应的排序顺序(true表示降序,false表示升序)
        //此处可以根据业务传具体字段的具体排序方式,此处测试就先写死
        sortOrders.put("ys1", false);
        sortOrders.put("ys2", true);
        sortOrders.put("ys3", true);

        anyProperListOfReflectSort(list, sortProperties, sortOrders);
        return list;
    }

    private static List<JSONObject> jsonObjects() {
        List<JSONObject> jsonList = new ArrayList<>();

        // 添加JSONObject对象到List中
        JSONObject json1 = new JSONObject();
        json1.put("id", 1);
        json1.put("name", "Alice");
        json1.put("age", 25);
        json1.put("color", 11.0);

        JSONObject json2 = new JSONObject();
        json2.put("id", 2);
        json2.put("name", "Alice");
        json2.put("age", 25);
        json2.put("color", 10.0);

        JSONObject json3 = new JSONObject();
        json3.put("id", 3);
        json3.put("name", "Bob");
        json3.put("age", 20);
        json3.put("color", 13.0);

        jsonList.add(json1);
        jsonList.add(json2);
        jsonList.add(json3);

        List<String> sortProperties = new ArrayList<>();
        //动态指定要排序的属性字段
        //此处可以根据业务需要传具体字段,此处测试就先写死
        sortProperties.add("name");
        sortProperties.add("age");
        sortProperties.add("color");

        Map<String, Boolean> sortOrders = new HashMap<>();
        //动态指定属性字段对应的排序顺序(true表示降序,false表示升序)
        //此处可以根据业务传具体字段的具体排序方式,此处测试就先写死
        sortOrders.put("name", true);
        sortOrders.put("age", true);
        sortOrders.put("color", true);
        List<JSONObject> jsonObjects = anyProperListSort(jsonList, sortProperties, sortOrders);
        return jsonObjects;
    }

    /**
     * 场景一:javaObject集合 转JSONObject集合,动态指定多个要排序的字段
     * @return
     */
    private static List<WxObj> javaObjectToJsonObjectList() {
        WxObj a = new WxObj("w",10.00,20.00,10.00,20.00,10.00);
        WxObj b = new WxObj("w",10.00,20.00,12.00,20.00,10.00);
        WxObj c = new WxObj("w",12.00,10.00,10.00,20.00,10.00);
        WxObj d = new WxObj("w",12.00,20.00,10.00,20.00,10.00);
        List<WxObj> list = new ArrayList<WxObj>();
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);

        List<String> sortProperties = new ArrayList<>();
        //动态指定要排序的属性字段
        //此处可以根据业务需要传具体字段,此处测试就先写死
        sortProperties.add("ys1");
        sortProperties.add("ys2");
        sortProperties.add("ys3");

        Map<String, Boolean> sortOrders = new HashMap<>();
        //动态指定属性字段对应的排序顺序(true表示降序,false表示升序)
        //此处可以根据业务传具体字段的具体排序方式,此处测试就先写死
        sortOrders.put("ys1", false);
        sortOrders.put("ys2", true);
        sortOrders.put("ys3", true);
        List<JSONObject> json = new ArrayList<>();
        for (WxObj wxObj : list) {
            JSONObject o = JSONObject.parseObject(JSON.toJSONString(wxObj));
            json.add(o);
        }

        List<JSONObject> jsonObjects = anyProperListSort(json, sortProperties, sortOrders);
        List<WxObj> wxObjs = new ArrayList<>();
        jsonObjects.stream().forEach(e -> {
            wxObjs.add(JSONObject.toJavaObject(e, WxObj.class));
        });
        return wxObjs;
    }

    /**
     * 按任意给定集合进行排序,升序或降序由flag决定
     *
     * @param list
     * @param sortProperties
     * @param sortOrders
     * @return
     */
    @SuppressWarnings("unchecked")
    public static List<JSONObject> anyProperListSort(List<JSONObject> list, List<String> sortProperties, Map<String, Boolean> sortOrders) {
        Comparator<JSONObject> comparator = null;

        for (int i = 0; i < sortProperties.size(); i++) {
            final int propertyIndex = i;
            Comparator<JSONObject> propertyComparator = Comparator.comparing(
                    (JSONObject o) -> o.getString(sortProperties.get(propertyIndex)),
                    String.CASE_INSENSITIVE_ORDER
            );

            if (sortOrders.get(sortProperties.get(propertyIndex))) {
                propertyComparator = propertyComparator.reversed();
            }

            if (comparator == null) {
                comparator = propertyComparator;
            } else {
                comparator = comparator.thenComparing(propertyComparator);
            }
        }
        Collections.sort(list, comparator);
        return list;
    }

    /**
     * 按任意给定集合进行排序,升序或降序由flag决定
     *
     * @param list 对象
     * @param sortProperties
     * @param sortOrders
     * @return
     */
    private static void anyProperListOfReflectSort(List<WxObj> list, List<String> sortProperties, Map<String, Boolean> sortOrders) throws NoSuchMethodException {
        // 构建Comparator链
        Comparator<WxObj> comparator = null;
        for (int i = 0; i < sortProperties.size(); i++) {
            final int propertyIndex = i;
            Class clazz = WxObj.class;
            Method method = clazz.getMethod("get" + sortProperties.get(propertyIndex).substring(0, 1).toUpperCase() + sortProperties.get(propertyIndex).substring(1));
            Comparator<WxObj> propertyComparator = Comparator.comparing(
                wxObj -> {
                    try {
                        return (double)method.invoke(wxObj);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        throw new RuntimeException(e);
                    }
                }
            );

            if (sortOrders.get(sortProperties.get(propertyIndex))) {
                propertyComparator = propertyComparator.reversed();
            }

            if (comparator == null) {
                comparator = propertyComparator;
            } else {
                comparator = comparator.thenComparing(propertyComparator);
            }
        }
        Collections.sort(list, comparator);
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class WxObj {
        private String wxObj;
        private Double ys1;
        private Double ys2;
        private Double ys3;
        private Double ys4;
        private Double ys5;
    }
}

二、 按任意属性进行排序(单个属性)

java 复制代码
package com.example.gateway;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author wux
 * @version 1.0.0
 * @description 按任意属性进行排序(单个属性)
 * @date 2024/11/28 16:24
 */
public class SortUtil {
    public static void main(String[] args) {
        WxObj a = new WxObj("w",10.00,20.00,10.00,20.00,10.00);
        WxObj b = new WxObj("w",10.00,10.00,10.00,20.00,10.00);
        WxObj c = new WxObj("w",12.00,10.00,10.00,20.00,10.00);
        WxObj d = new WxObj("w",12.00,20.00,10.00,20.00,10.00);
        List<WxObj> list = new ArrayList<WxObj>();
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        anyProperSort(list, "ys1", true);
        list.stream().forEach(System.out::println);
    }

    /**
     * @description 按任意属性进行排序(单个属性)
     * @author wux
     * @date 2024/12/11 14:35
     * @version 1.0.0
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static class AnyProperComparator implements Comparator<Object> {

        private String properName;// 根据此关键字属性排序

        private boolean flag;// 为true的时候是正序,为false的时候是倒序

        /**
         * 实现Comparator的对比方法
         *
         * @param r1
         * @param r2
         */
        @Override
        @SuppressWarnings("unchecked")
        public int compare(Object r1, Object r2) {
            Class c = r1.getClass();
            double result = 0;
            try {
                Field field = c.getDeclaredField(properName);
                String classType = field.getType().getSimpleName();
                Method method = null;
                // 这里仅根据方法的返回值类型的名称来判定,比较方便
                if ("String".equals(classType)) {
                    method = c.getMethod("get" + properName.substring(0, 1).toUpperCase() + properName.substring(1), new Class[] {});
                    if (flag) {
                        result = ((String) method.invoke(r1)).compareTo((String) method.invoke(r2));
                    } else {
                        result = ((String) method.invoke(r2)).compareTo((String) method.invoke(r1));
                    }

                } else if ("Integer".equals(classType) || "int".equals(classType)) {
                    method = c.getMethod("get" + properName.substring(0, 1).toUpperCase() + properName.substring(1), new Class[] {});
                    if (flag) {
                        result = ((Integer) method.invoke(r1)) - ((Integer) method.invoke(r2));
                    } else {
                        result = ((Integer) method.invoke(r2)) - ((Integer) method.invoke(r1));
                    }
                } else if ("Double".equals(classType) || "double".equals(classType)) {
                    method = c.getMethod("get" + properName.substring(0, 1).toUpperCase() + properName.substring(1), new Class[] {});
                    if (flag) {
                        result = ((Double) method.invoke(r1)) - ((Double) method.invoke(r2));
                    } else {
                        result = ((Double) method.invoke(r2)) - ((Double) method.invoke(r1));
                    }
                } else if ("Float".equals(classType) || "float".equals(classType)) {
                    method = c.getMethod("get" + properName.substring(0, 1).toUpperCase() + properName.substring(1), new Class[] {});
                    if (flag) {
                        result = ((Float) method.invoke(r1)) - ((Float) method.invoke(r2));
                    } else {
                        result = ((Float) method.invoke(r2)) - ((Float) method.invoke(r1));
                    }
                } else {
                    System.out.println("属性排序只支持数据类型和String类型,其它类型暂不支持。");
                    result = -100;
                }
            } catch (SecurityException | NoSuchFieldException | InvocationTargetException | NoSuchMethodException | IllegalArgumentException | IllegalAccessException e ) {
                e.printStackTrace();
            }

            // 确定返回值
            if (result > 0) {
                return 1;
            } else if (result < 0) {
                return -1;
            }
            return 0;
        }
    }

    /**
     * 按任意给定的字段进行排序,升序或降序由flag决定
     *
     * @param list
     * @param properName
     * @param flag
     * @return
     */
    @SuppressWarnings("unchecked")
    public static List<WxObj> anyProperSort(List<WxObj> list, String properName, boolean flag) {
        AnyProperComparator comparator = new AnyProperComparator(properName, flag);
        Collections.sort(list, comparator);
        return list;
    }
}
相关推荐
O(1)的boot15 分钟前
微服务的问题
java·数据库·微服务
一个略懂代码的程序员18 分钟前
Redis01
java·redis
IT界的奇葩22 分钟前
基于springboot使用Caffeine
java·spring boot·后端·caffeine
西埃斯迪恩-霖33 分钟前
Idea导入SpringBoot3.2.x源码
java·ide·intellij-idea
m0_748251721 小时前
Spring Boot 经典九设计模式全览
java·spring boot·设计模式
潘多编程1 小时前
Spring Boot性能提升:实战案例分析
java·spring boot·后端
m0_748256141 小时前
Spring Boot 整合 Keycloak
java·spring boot·后端
#HakunaMatata1 小时前
Java 中 List 接口的学习笔记
java·学习·list
Ase5gqe1 小时前
Spring Boot中实现JPA多数据源配置指南
java
AI人H哥会Java1 小时前
【JAVA】Java高级:多数据源管理与Sharding:在Spring Boot应用中实现多数据源的管理
java·开发语言