java中常常有一些需求难以用SQL排序,需要在内存中排序。
常规的java8lambda不能动态指定字段
常规的实现Comparator的compare方法需要配合反射工具类操作。
上stackoverflow发现,使用ComparatorChain类可以根据字段名进行排序
那就尝试改造这个需求吧。
关键代码
chain.addComparator(new BeanComparator("filedName"), false);
filedName为排序字段,false/true可以指定是否升序降序。
但是这个对于字段/属性为null时会报错,没有null安全性,需要在字段上加nullsLast
new BeanComparator("filedName")需要改成new BeanComparator("filedName",Comparator.nullsLast(Comparator.naturalOrder())))
完整代码如下:
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.comparators.ComparatorChain;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author gsls200808
* List 排序,内存排序 支持多字段,每个字段可指定排序方向,解析order by子句参数排序
*/
public class CompareUtil {
private static Pattern linePattern = Pattern.compile("_([a-z])");
private static Pattern humpPattern = Pattern.compile("\\B(\\p{Upper})(\\p{Lower}*)");
/*
*@param list 需要排序的list
*@param orderBy SQL中的orderBy子句/前端传的orderBy参数 需要与实体字段保持一致。
*/
public static <T> void sort(List<T> list, String orderBy) {
if (orderBy == null || orderBy.length() == 0) {
return;
}
ComparatorChain chain = new ComparatorChain();
String[] strArray = orderBy.split(",");
for (String str : strArray) {
//数组提取升降序
//去掉首尾空格
String str2 = str.trim();
//字段和升降序条件可能存在多个空格
String[] arr = str2.split("\\s+");
//解析property
String property = arr[0];
//解析reverse false升序排序,true降序排序
boolean reverse = false;
if (arr.length > 1 && "desc".equals(arr[1].toLowerCase())) {
reverse = true;
}
//false升序排序,true降序排序
chain.addComparator((new BeanComparator(property,Comparator.nullsLast(Comparator.naturalOrder()))), reverse);
}
Collections.sort(list, chain);
}
/**
* 下划线转驼峰
*
* @param str
* @return
*/
public static String lineToHump(String str) {
Matcher matcher = linePattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString();
}
}