最近遇到了一个问题,那就是数据直接通过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;
}
}
}