【工具类】java代码实现分页与多字段排序

支持对list进行分页,支持数字、字符串、日期类型、金额类型等多字段排序

  POM文件中导入依赖

<!-- hutool工具类 -->
<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.8.21</version>
</dependency>

<!-- lombok -->
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<version>1.18.28</version>
	<scope>provided</scope>
</dependency>

实体类

import lombok.Data;

@Data
public class OrderItem {

    /**
     * 排序字段
     */
    private String column;

    /**
     * 排序规则
     */
    private Boolean order;

    public OrderItem() {
    }

    public OrderItem(String column, Boolean order) {
        this.column = column;
        this.order = order;
    }
}

import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serial;
import java.io.Serializable;
import java.util.List;

@Data
@NoArgsConstructor
public class PageInfo<T> implements Serializable {

    @Serial
    private static final long serialVersionUID = -3679428352166664373L;

    /**
     * 总记录数
     */
    private Long total;

    /**
     * 结果集
     */
    private List<T> list;

    public PageInfo(Long total, List<T> list) {
        this.list = list;
        this.total = total;
    }

}

工具类的实现

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.smartadmin.common.model.api.OrderItem;
import com.smartadmin.common.model.api.PageInfo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;

public class PageUtil {

    public static <T> List<T> startPage(List<T> list, Func1<T, ?>  column, Boolean isAsc) {
        String orderBy = LambdaUtil.getFieldName(column) + CharSequenceUtil.SPACE + (isAsc ? "asc" : "desc");
        return startPage(list, null, null, orderBy).getList();
    }

    /**
     * 排序
     *
     * @param list 数据源
     * @param orderBy 排序 示例:"bigDecimal desc, localDateTime asc"
     * @return 排序结果
     */
    public static <T> List<T> startPage(List<T> list, String orderBy) {
        return startPage(list, null, null, orderBy).getList();
    }

    /**
     * 分页
     *
     * @param list 数据源
     * @param pageNum 当前页码
     * @param pageSize 每页查询数
     * @param <T> 泛型
     * @return 分页结果
     */
    public static <T> PageInfo<T> startPage(List<T> list, int pageNum, int pageSize) {
        return startPage(list, pageNum, pageSize, null);
    }

    /**
     * 排序分页
     *
     * @param list 数据源
     * @param pageNum 当前页码
     * @param pageSize 每页查询数
     * @param orderBy 排序 示例:"bigDecimal desc, localDateTime asc"
     * @param <T> 泛型
     * @return 分页结果
     */
    public static <T> PageInfo<T> startPage(List<T> list, Integer pageNum, Integer pageSize, String orderBy) {
        if (CollUtil.isEmpty(list)) {
            return new PageInfo<>(0L, new ArrayList<>(0));
        }

        // 大于5000条数据使用多线程
        long total = list.size();
        Stream<T> stream;
        if(total > 5000) {
            stream = list.parallelStream();
        } else {
            stream = list.stream();
        }

        // 进行排序
        if(CharSequenceUtil.isNotBlank(orderBy)){
            Comparator<? super T> comparator = createComparator(orderBy);
            if(ObjectUtil.isNotEmpty(comparator)){
                stream = stream.sorted(comparator);
            }
        }

        // 进行分页
        if(ObjectUtil.isNotEmpty(pageNum) && ObjectUtil.isNotEmpty(pageSize)){
            int startPage = (pageNum - 1) * pageSize;
            int endPage = pageNum * pageSize;
            stream = stream.skip(startPage).limit(endPage);
        }

        return new PageInfo<>(total, stream.toList());
    }

    private static <T> Comparator<? super T> createComparator(String orderBy) {
        if(CharSequenceUtil.isBlank(orderBy)) {
            return null;
        }

        List<OrderItem> orderItems = Arrays.stream(orderBy.split(StrPool.COMMA)).map(s -> {
            String[] strings = s.split(CharSequenceUtil.SPACE);
            return new OrderItem(StrUtil.lowerFirst(StrUtil.toCamelCase(strings[0])), CharSequenceUtil.equals("desc", strings[1]));
        }).toList();

        if(ObjectUtil.isEmpty(orderItems)) {
            return null;
        }

        Comparator<? super T> comparator = (o1, o2) -> {
            Object filed1 = ReflectUtil.getFieldValue(o1, orderItems.get(0).getColumn());
            Object filed2 = ReflectUtil.getFieldValue(o2, orderItems.get(0).getColumn());
            if(filed1 instanceof Comparable integer1 && filed2 instanceof Comparable integer2) {
                if(orderItems.get(0).getOrder()) {
                    return integer2.compareTo(integer1);
                } else {
                    return integer1.compareTo(integer2);
                }
            }

            return CompareUtil.compare(filed1, filed2, orderItems.get(0).getOrder());
        };

        for (int i = 1; i < orderItems.size(); i++) {
            OrderItem orderItem = orderItems.get(i);
            comparator.thenComparing((o1, o2) -> {
                Object filed1 = ReflectUtil.getFieldValue(o1, orderItem.getColumn());
                Object filed2 = ReflectUtil.getFieldValue(o2, orderItem.getColumn());
                if(filed1 instanceof Comparable integer1 && filed2 instanceof Comparable integer2) {
                    if(Boolean.TRUE.equals(orderItem.getOrder())) {
                        return integer2.compareTo(integer1);
                    } else {
                        return integer1.compareTo(integer2);
                    }
                }

                if(Boolean.TRUE.equals(orderItem.getOrder())) {
                    return CompareUtil.compare(filed1, filed2, false);

                } else {
                    return CompareUtil.compare(filed2, filed1, false);

                }
            });
        }
        return comparator;
    }
    
}

测试

import com.smartadmin.common.model.api.PageInfo;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student("3张三", 18, LocalDate.parse("2024-09-18")));
        studentList.add(new Student("5王五", 18, LocalDate.parse("2024-09-17")));
        studentList.add(new Student("5王六", 19, LocalDate.parse("2024-09-17")));
        studentList.add(new Student("4李四", 18, LocalDate.parse("2024-09-13")));
        studentList.add(new Student("4李四", 18, LocalDate.parse("2024-09-14")));

        PageInfo<Student> pageInfo = PageUtil.startPage(studentList, 1, 2, "name asc, age asc, admissionDate asc");
        System.out.println(pageInfo);
    }
}

@Data
@AllArgsConstructor
class Student{

    // 姓名
    private String name;

    // 年纪
    private Integer age;

    // 入学日期
    private LocalDate admissionDate;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值