一、需求
现有一个业务,需要根据表头字段对返回的数据进行升序、降序排序,目前只支持数字类型,如图:
二、pom依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.4</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!--spring-mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
<exclusions>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
<scope>compile</scope>
</dependency>
三、创建前端查询实体
package com.example.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* @version 1.0
* @description:
* @date 2023/3/29 14:54
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true) //忽略前端的传递的额外字段
public class OrderBySqlQuery {
/**
* 根据名称搜索
*/
private String name;
/**
* 当前页
*/
private Integer pageNum;
/**
* 每页大小
*/
private Integer pageSize;
/**
* 排序的列字段
*/
private String column;
/**
* 排序规则默认降序 降序:false 升序:true
*/
private Boolean asc;
public Boolean getAsc() {
return asc == null ? false : asc;
}
}
四、创建前端返回实体
package com.example.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.math.BigDecimal;
/**
* @version 1.0
* @description:
* @date 2023/3/29 14:54
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true) //忽略前端的传递的额外字段
public class OrderBySqlData {
private Long id;
/**
* 名称
*/
private String name;
/**
* 年龄
*/
private int age;
/**
* 捐款
*/
private BigDecimal fee;
public OrderBySqlData() {
}
public OrderBySqlData(Long id, String name, int age,BigDecimal fee) {
this.id = id;
this.name = name;
this.age = age;
this.fee = fee;
}
}
五、定义mapper类
package com.example.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.dto.OrderBySqlData;
public interface OrderByDataMapper extends BaseMapper<OrderBySqlData> {
}
六、抽离工具类
package com.example.util;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Description 对集合自定义排序
* @Date: 上午10:27 2023/4/17
*/
@Slf4j
public class OrderForList {
/**
* 第一种写法 Java8
* Java内存对list进行动态排序
* 前端传入需要排序的字段,以及排序规则
* 将对比的字段类型转换成double类型再进行对比 不支持中文
* <p>
*
*
* @param t
* @param sortFiled1 前端传入需要排序的字段
* @param orderBy 排序规则 降序:false 升序:true
* @param <T>
* @return
*/
public static <T> List<T> orderSort(List<T> t, String sortFiled1, Boolean orderBy) {
if (CollectionUtils.isEmpty(t))
return new ArrayList<>();
if (StringUtils.isBlank(sortFiled1) || null == orderBy) {
return t;
}
//将首字母大写
String sortFiled = firstLetterName(sortFiled1);
return t.stream().sorted((o1, o2) -> {
try {
double obj3 = 0;
double obj4 = 0;
//获取本类中的所有方法,包括私有的(private、protected、默认以及public)的方法
Method methodOne = o1.getClass().getDeclaredMethod("get" + sortFiled);
if (null != methodOne.invoke(o1)) {
//获取字段的值
String obj1 = String.valueOf(methodOne.invoke(o1));
if (StringUtils.isNotBlank(obj1) && StringUtils.isNotBlank(obj1.trim().replaceAll("\\,|\\.\\%", ""))) {
//特殊字符串处理 以及将字符串转成十进制的double类型数据
obj3 = Double.parseDouble(obj1.replaceAll("\\,|\\.\\%", ""));
}
}
Method methodTwo = o2.getClass().getDeclaredMethod("get" + sortFiled);
if (null != methodTwo.invoke(o2)) {
String obj2 = String.valueOf(methodTwo.invoke(o2));
if (StringUtils.isNotBlank(obj2) && StringUtils.isNotBlank(obj2.trim().replaceAll("\\,|\\.\\%", ""))) {
//特殊字符串处理 以及将字符串转成十进制的double类型数据
obj4 = Double.parseDouble(obj2.replaceAll("\\,|\\.\\%", ""));
}
}
if (!orderBy) { //降序
return Double.compare(obj4, obj3);
} else if (orderBy) { //升序
return Double.compare(obj3, obj4);
}
} catch (Exception e) {
log.info("异常:" + e.getMessage());
}
return -1;
}).collect(Collectors.toList());
}
/**
* 第二种写法 Collections 工具类
* Java内存对list进行动态排序
* 前端传入需要排序的字段,以及排序规则
* 将对比的字段类型转换成double类型再进行对比 不支持中文
*
* 优点:支持所有返回值字段(int,long,float,double,BigDecimal)排序
* 缺点:只能内存排序,数据量大的时候效率极低
*
* @param t
* @param sortFiled1 前端传入需要排序的字段
* @param orderBy 排序规则 降序:false 升序:true
* @param <T>
* @return
*/
public static <T> List<T> orderSortTwo(List<T> t, String sortFiled1, Boolean orderBy) {
String sortFiled = firstLetterName(sortFiled1);
Collections.sort(t, new Comparator<T>() {
@Override
public int compare(T o1, T o2) {
double obj3 = 0;
double obj4 = 0;
try {
//获取本类中的所有方法,包括私有的(private、protected、默认以及public)的方法
Method methodOne = o1.getClass().getDeclaredMethod("get" + sortFiled);
//获取字段的值
String obj1 = String.valueOf(methodOne.invoke(o1));
if (StringUtils.isNotBlank(obj1) && StringUtils.isNotBlank(obj1.trim().replaceAll("\\,|\\.\\%", ""))) {
//特殊字符串处理 以及将字符串转成十进制的double类型数据
obj3 = Double.parseDouble(obj1.replaceAll("\\,|\\.\\%", ""));
}
Method methodTwo = o2.getClass().getDeclaredMethod("get" + sortFiled);
String obj2 = String.valueOf(methodTwo.invoke(o2));
if (StringUtils.isNotBlank(obj2) && StringUtils.isNotBlank(obj2.trim().replaceAll("\\,|\\.\\%", ""))) {
//特殊字符串处理 以及将字符串转成十进制的double类型数据
obj4 = Double.parseDouble(obj2.replaceAll("\\,|\\.\\%", ""));
}
if (!orderBy) { //降序
return Double.compare(obj4, obj3);
} else if (orderBy) { //升序
return Double.compare(obj3, obj4);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return 0;
}
});
return t;
}
/**
* 将传入的字符串首字母大写
*
* @param name
* @return
*/
public static String firstLetterName(String name) {
char[] cs = name.toCharArray();
cs[0] -= 32;
return String.valueOf(cs);
}
}
七、编写service
package com.example.service;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.example.dto.OrderBySqlData;
import com.example.dto.OrderBySqlQuery;
import com.example.mapper.OrderByDataMapper;
import com.example.util.HumpNamedUtils;
import com.example.util.OrderForList;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
/**
* @Description 根据一个字段动态排序
* @Date: 下午4:40 2023/4/17
*/
@Slf4j
public class OrderByService {
@Autowired
private OrderByDataMapper orderByDataMapper;
/**
* 根据前端传入的排序字段,以及排序规则
* 使用MybatisPlus进行动态排序
*
* @param query
* @return
*/
public List OrderBySql(OrderBySqlQuery query) {
QueryWrapper<OrderBySqlData> queryWrapper = new QueryWrapper<>();
//将queryWrapper转为lambdaQueryWrapper,然后再进行条件搜索
queryWrapper.lambda().eq(OrderBySqlData::getName, query.getName());
//处理排序 升序
if (StringUtils.isNotBlank(query.getColumn()) && query.getAsc()) {
queryWrapper.orderByAsc(HumpNamedUtils.hump2LowerColumnName(query.getColumn()));
}
//处理排序 降序
if (StringUtils.isNotBlank(query.getColumn()) && !query.getAsc()) {
queryWrapper.orderByDesc(HumpNamedUtils.hump2LowerColumnName(query.getColumn()));
}
//查询数据库
return orderByDataMapper.selectList(queryWrapper);
}
/**
* 使用Java内存进行排序 第一种写法 Java8
*
* @param query
* @return
*/
public static void OrderByJava(OrderBySqlQuery query) {
//模拟数据
List<OrderBySqlData> orderBySqlData = Arrays.asList(new OrderBySqlData(1L, "张三", 12, BigDecimal.valueOf(100.5)), new OrderBySqlData(2L, "李四", 13, BigDecimal.valueOf(21.51)));
List<OrderBySqlData> feeAsc = OrderForList.orderSort(orderBySqlData, query.getColumn(), query.getAsc());
log.info("**************************第一种写法 Java8:" + JSON.toJSONString(feeAsc));
List<OrderBySqlData> feeDesc1 = OrderForList.orderSortTwo(orderBySqlData, query.getColumn(), query.getAsc());
log.info("**************************第二种写法 Collections 工具类:" + JSON.toJSONString(feeDesc1));
}
}
八、测试
/**
* 测试
*
* @param args
*/
public static void main(String[] args) {
//根据捐款字段降序
OrderBySqlQuery query = new OrderBySqlQuery();
query.setColumn("fee");
query.setAsc(false);
OrderByJava(query);
//根据捐款字段升序
OrderBySqlQuery query1 = new OrderBySqlQuery();
query1.setColumn("fee");
query1.setAsc(true);
OrderByJava(query1);
}
结果:
九、开源仓库地址
Gitee仓库:https://gitee.com/Dev9925/custom-sorting-demo
GitHub仓库: