最近遇到了一個問題,那就是數據直接通過sql計算會很慢,或者是計算不出來,那么計算數據的任務只能交給java后台。
計算完數據之后,需要對數據進行排序,分頁。
如果知道固定的排序規則好辦,但是如果不知道規則,或者規則過多,就需要考慮通用性
而下面就是我的排序方案:
總體思路是:
- 判斷是否為空
- 通過第0個元素的數據獲取field的列表,考慮到了可能存在通過數據的某一屬性的某一屬性進行排序的可能
- 生成Map<排序字段, List<數據>>的數據,使用list考慮到了可能存在並列數據的可能,另外被排序的數據需要實現Comparable接口,並且泛型值要寫上
- lambda對數據進行排序
- 對最終數據進行處理
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
public class A {
private static final Logger logger = LoggerFactory.getLogger(A.class);
/**
* 排序
*
* @param dataList
* @param fieldNameList
* @param isAsc
* @param <T>
* @param <C>
* @return
*/
public static <T, C extends Comparable<C>> List<T> sort (List<T> dataList, List<String> fieldNameList, boolean isAsc) {
List<Field> fieldList = new ArrayList<>();
if (ObjectUtils.isEmpty(dataList)) {
return dataList;
}
Class<?> dataClass = dataList.get(0).getClass();
for (String name : fieldNameList) { // 循環獲取field列表
Field field = getField(dataClass, name);
fieldList.add(field);
dataClass = field.getType();
}
Map<C, List<T>> dataMap = new HashMap(); // 有多條數據同一值的可能
dataList.forEach(data -> { // 獲取數據Map,
C key = (C) getData(data, fieldList);
if (dataMap.containsKey(key)) {
dataMap.get(key).add(data);
} else {
dataMap.put(key, new ArrayList<T>() {{
add(data);
}});
}
});
List<List<T>> tempList;
if (isAsc) { // 升序
tempList = dataMap.entrySet().stream().sorted(Map.Entry.comparingByKey(Comparator.nullsFirst(Comparator.naturalOrder())))
.map(Map.Entry::getValue).collect(Collectors.toList());
} else { // 降序
tempList = dataMap.entrySet().stream().sorted(Map.Entry.comparingByKey(Comparator.nullsFirst(Comparator.reverseOrder())))
.map(Map.Entry::getValue).collect(Collectors.toList());
}
List<T> resultList = new ArrayList<T>();
tempList.forEach(data -> {
data.forEach(d -> {
resultList.add(d);
});
});
return resultList;
}
/**
* 根據field列表,獲取數據
* @param source
* @param fieldList
* @return
*/
public static Object getData (Object source, List<Field> fieldList) {
try {
Object obj = fieldList.get(0).get(source);
if (fieldList.size() == 1) {
return obj;
}
return getDataRecursion(obj, fieldList.subList(1, fieldList.size())); // 多條數據,遞歸查詢
} catch (IllegalAccessException e) {
logger.error("", e);
}
return source;
}
/**
* 遞歸獲取屬性列表
* @param source
* @param fieldList
* @return
*/
public static Object getDataRecursion (Object source, List<Field> fieldList) {
for (Field field : fieldList) {
try {
source = field.get(source);
} catch (IllegalAccessException e) {
logger.error("", e);
}
}
return source;
}
/**
* 根據name,獲取class的Field
* @param dataClass
* @param fieldName
* @return
*/
public static Field getField (Class dataClass, String fieldName) {
Field field = getEntityFieldByFieldName(dataClass, fieldName);
return field;
}
/**
* 根據屬性名,獲取對象field,field可獲取數據
*/
public static <T> Field getEntityFieldByFieldName (Class clazz, String fieldName) {
try {
// 尋找泛型Field
Field targetField = null;
for (; clazz != null; clazz = clazz.getSuperclass()) {
Field[] fields = clazz.getDeclaredFields();
try {
targetField = clazz.getDeclaredField(fieldName);
break;
} catch (Exception e) {
continue;
}
}
targetField.setAccessible(true);
return targetField;
} catch (Exception e) { // 這個異常基本不可能發生,若發生就是因為程序出現了bug,那就讓你空指針吧
logger.error("", e);
return null;
}
}
}
