1. 程式人生 > >Java8 對矩陣進行組合排序

Java8 對矩陣進行組合排序

首先,常規的實體類的多條件排序可參考:

Java8:Lambda表示式增強版Comparator和排序

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);