支持对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;
}