java8动态多字段排序内存排序模拟sql排序

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
 * java8动态多字段排序,根据前端传入的多个字段,在内存中进行排序
 * 4
 */
@Slf4j
public class DynamicMultiFieldSortUtil {


    /**
     * 该静态对象用来排序
     */
    static class Sample {
        Long id;
        BigDecimal money;
        LocalDate createDate;

        public long getId() {
            return id;
        }

        public void setId(long id) {
            this.id = id;
        }

        public BigDecimal getMoney() {
            return money;
        }

        public void setMoney(BigDecimal money) {
            this.money = money;
        }

        public LocalDate getCreateDate() {
            return createDate;
        }

        public void setCreateDate(LocalDate createDate) {
            this.createDate = createDate;
        }

        /**
         * 方便把list打印成字符串
         *
         * @return
         */
        @Override
        public String toString() {
            return "Sample{" +
                    "id=" + id +
                    ", money=" + money +
                    ", createDate=" + createDate +
                    '}';
        }
    }

    /**
     * 排序静态类
     */
    static class OrderByFields {
        //排序字段
        String field;
        //升序 true,降序false
        boolean isAsc;

        public String getField() {
            return field;
        }

        public void setField(String field) {
            this.field = field;
        }

        public boolean isAsc() {
            return isAsc;
        }

        public void setAsc(boolean asc) {
            isAsc = asc;
        }
    }

    //模拟前端数据,静态页对象
    static class Pages {
        //当前页
        int current;
        //页大小
        int size;
        //排序的字段集合
        List<OrderByFields> orderByFields;

        public int getCurrent() {
            return current;
        }

        public void setCurrent(int current) {
            this.current = current;
        }

        public int getSize() {
            return size;
        }

        public void setSize(int size) {
            this.size = size;
        }

        public List<OrderByFields> getOrderByFields() {
            return orderByFields;
        }

        public void setOrderByFields(List<OrderByFields> orderByFields) {
            this.orderByFields = orderByFields;
        }
    }

    public static void main(String[] args) {
        //模拟前端数据
        Pages pages = new Pages();
        pages.setCurrent(1);
        pages.setSize(10);
        List<OrderByFields> list = new ArrayList<>();

        //id升序
        OrderByFields orderByFields1 = new OrderByFields();
        orderByFields1.setField("id");
        orderByFields1.setAsc(true);
        list.add(orderByFields1);
        //金额降序
        OrderByFields orderByFields2 = new OrderByFields();
        orderByFields2.setField("money");
        orderByFields2.setAsc(false);
        list.add(orderByFields2);
        //创建时间升序
        OrderByFields orderByFields3 = new OrderByFields();
        orderByFields3.setField("createDate");
        orderByFields3.setAsc(true);
        list.add(orderByFields3);

        pages.setOrderByFields(list);

        List<Sample> waitSortList = new ArrayList<>();
        //第一个对象
        Sample sample1 = new Sample();
        sample1.setCreateDate(LocalDate.now());
        sample1.setId(111L);
        sample1.setMoney(BigDecimal.valueOf(99L));
        waitSortList.add(sample1);
//        第二个
        Sample sample2 = new Sample();
        sample2.setCreateDate(LocalDate.now().minusDays(1));
        sample2.setId(-1L);
        sample2.setMoney(BigDecimal.valueOf(100L));
        waitSortList.add(sample2);
//        第三个
        Sample sample3 = new Sample();
        sample3.setCreateDate(LocalDate.now().minusDays(1));
        sample3.setId(111L);
        sample3.setMoney(BigDecimal.valueOf(99L));
        waitSortList.add(sample3);

        System.out.println(waitSortList.toString());

        List<Sample> sort = sort(pages, waitSortList);

        System.out.println(sort.toString());

    }

    //排序入口
    public static <T> List<T> sort(Pages page, List<T> list) {
        return list.stream()
                .sorted(dynamicComparator(page))
                .collect(Collectors.toList());
    }

    //    自定义动态字段比较器,模拟sql完整排序功能
    private static <T> Comparator<T> dynamicComparator(Pages page) {
        //动态比较器
        Comparator<T> dynamicComparator = null;
        List<OrderByFields> orderByFields = page.getOrderByFields();
        for (int i = 0; i < orderByFields.size(); i++) {
            String field = orderByFields.get(i).getField();
            //第一个排序字段优先级最高,使用comparing
            if (i == 0) {
                dynamicComparator = Comparator.comparing((T x) ->
                        get(x, field), orderByFields.get(i).isAsc ? Comparator.naturalOrder() : Comparator.reverseOrder()
                );
            }else {
                dynamicComparator = dynamicComparator.thenComparing((T x) ->
                        get(x, field), orderByFields.get(i).isAsc ? Comparator.naturalOrder() : Comparator.reverseOrder()
                );
            }
        }
        return dynamicComparator;
    }

    /**
     * 反射获取值
     * list<E> E非静态类时,可以把方法放入E对象中
     * @param x
     * @param field
     * @return
     */
    private static BigDecimal get(Object x, Object field) {
        try {
            String name = field.toString();
            Field declaredField = x.getClass().getDeclaredField(name);
            declaredField.setAccessible(true);
            Object obj = declaredField.get(x);
            //空值默认为最小值
            if (obj == null) {
                return BigDecimal.valueOf(Integer.MIN_VALUE);
            }
            if (declaredField.getType().equals(BigDecimal.class)) {
                return new BigDecimal(obj.toString());
            }
            if (declaredField.getType().equals(LocalDate.class)) {
                LocalDate result = (LocalDate) obj;
                return BigDecimal.valueOf(result.atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli());
            } else if (declaredField.getType().equals(Long.class)) {
                return BigDecimal.valueOf((Long) obj);
            } else {
                return BigDecimal.valueOf(Integer.MIN_VALUE);
            }
        } catch (Exception e) {
            log.error("失败", e);
        }
        return BigDecimal.valueOf(Integer.MIN_VALUE);
    }
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值