首先,常规的实体类的多条件排序可参考:
Java8:Lambda表达式增强版Comparator和排序
我们有个Matrix 多条件排序要求,矩阵的列动态生成,程序可以知道该列是定性的还是定量的值。用户在浏览这个Matrix 的时候,他会选择若干个列,每个列的升降序和排序优先级进行排序,后台负责做真分页排序。
比如一个matrix 的数据格式如下,java 使用的数据结构为:List<LinkedHashMap<String, Object>>,这样可以动态保存Matrix:
{"PERSON_ID":"11601","cataracta":"N","AGE":"50","GENDER":"N"},{"PERSON_ID":"10211","cataracta":"N","AGE":"51","GENDER":"Y"}
前端的排序请求体为:
{"analyseId":0,"cohortDefId":1960,"filters":[],"currentPage":1,"sort":{"AGE":"ASC","GENDER":"DESC"}}
主要是 sort 字段,排在前面的 AGE 优先级高于后面的 GENDER。明显地,AGE 是定量的值,GENDER是定性的。
程序先要根据用户选择的排序列构造一个 comparator 的列表,数据的值类型决定了比较的方式(comparator 里面的比较逻辑实现)。Comparator 的实例构造的方法有限,不得不先取一个 comparator 作为 nullsFirst 方法的参数实例化,然后就可以对剩余的 comparator 串行化,最后总的排序实例传给被排序的数据集进行排序。
LinkedList<Comparator<LinkedHashMap<String, Object>>> comparators = new LinkedList<>();
for (String varName : sortMap.keySet()){
if ("NUM".equals(varTypes.get(varName))){ // NUM 表示变量是定量的值,要转化为 BigDecimal 后进行比较
try {
comparators.add((Comparator<LinkedHashMap<String, Object>> & Serializable) (
LinkedHashMap<String, Object> o1,
LinkedHashMap<String, Object> o2) -> new BigDecimal(String.valueOf(o1.get(varName)))
.compareTo(new BigDecimal(String.valueOf(o2.get(varName)))));
} catch (Exception e) {
logger.error("当前变量在转型时出错,错误为::" + e.getMessage());
}
} else { // 定性的转化为 String 直接比较
comparators.add((Comparator<LinkedHashMap<String, Object>> & Serializable) (
LinkedHashMap<String, Object> o1,
LinkedHashMap<String, Object> o2) -> String.valueOf(o1.get(varName))
.compareTo(String.valueOf(o2.get(varName))));
}
}
logger.info("完成排序驱动的实例化");
Comparator sortings = Comparator.nullsFirst(comparators.poll()); // 先要构造一个 comparator 实例
List<String> rest = new ArrayList<>(sortMap.values());
rest.remove(rest.get(0));
for (String asc : rest){
sortings = sortings.thenComparing("asc".equalsIgnoreCase(asc) ? comparators.poll() : comparators.poll().reversed());
}
list.sort(sortings);