import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* java8动态多字段排序,根据前端传入的多个字段,在内存中进行排序
* 4
*/
@Slf4j
public class DynamicMultiFieldSortUtil {
/**
* 该静态对象用来排序
*/
static class Sample {
Long id;
BigDecimal money;
LocalDate createDate;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public BigDecimal getMoney() {
return money;
}
public void setMoney(BigDecimal money) {
this.money = money;
}
public LocalDate getCreateDate() {
return createDate;
}
public void setCreateDate(LocalDate createDate) {
this.createDate = createDate;
}
/**
* 方便把list打印成字符串
*
* @return
*/
@Override
public String toString() {
return "Sample{" +
"id=" + id +
", money=" + money +
", createDate=" + createDate +
'}';
}
}
/**
* 排序静态类
*/
static class OrderByFields {
//排序字段
String field;
//升序 true,降序false
boolean isAsc;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public boolean isAsc() {
return isAsc;
}
public void setAsc(boolean asc) {
isAsc = asc;
}
}
//模拟前端数据,静态页对象
static class Pages {
//当前页
int current;
//页大小
int size;
//排序的字段集合
List<OrderByFields> orderByFields;
public int getCurrent() {
return current;
}
public void setCurrent(int current) {
this.current = current;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public List<OrderByFields> getOrderByFields() {
return orderByFields;
}
public void setOrderByFields(List<OrderByFields> orderByFields) {
this.orderByFields = orderByFields;
}
}
public static void main(String[] args) {
//模拟前端数据
Pages pages = new Pages();
pages.setCurrent(1);
pages.setSize(10);
List<OrderByFields> list = new ArrayList<>();
//id升序
OrderByFields orderByFields1 = new OrderByFields();
orderByFields1.setField("id");
orderByFields1.setAsc(true);
list.add(orderByFields1);
//金额降序
OrderByFields orderByFields2 = new OrderByFields();
orderByFields2.setField("money");
orderByFields2.setAsc(false);
list.add(orderByFields2);
//创建时间升序
OrderByFields orderByFields3 = new OrderByFields();
orderByFields3.setField("createDate");
orderByFields3.setAsc(true);
list.add(orderByFields3);
pages.setOrderByFields(list);
List<Sample> waitSortList = new ArrayList<>();
//第一个对象
Sample sample1 = new Sample();
sample1.setCreateDate(LocalDate.now());
sample1.setId(111L);
sample1.setMoney(BigDecimal.valueOf(99L));
waitSortList.add(sample1);
// 第二个
Sample sample2 = new Sample();
sample2.setCreateDate(LocalDate.now().minusDays(1));
sample2.setId(-1L);
sample2.setMoney(BigDecimal.valueOf(100L));
waitSortList.add(sample2);
// 第三个
Sample sample3 = new Sample();
sample3.setCreateDate(LocalDate.now().minusDays(1));
sample3.setId(111L);
sample3.setMoney(BigDecimal.valueOf(99L));
waitSortList.add(sample3);
System.out.println(waitSortList.toString());
List<Sample> sort = sort(pages, waitSortList);
System.out.println(sort.toString());
}
//排序入口
public static <T> List<T> sort(Pages page, List<T> list) {
return list.stream()
.sorted(dynamicComparator(page))
.collect(Collectors.toList());
}
// 自定义动态字段比较器,模拟sql完整排序功能
private static <T> Comparator<T> dynamicComparator(Pages page) {
//动态比较器
Comparator<T> dynamicComparator = null;
List<OrderByFields> orderByFields = page.getOrderByFields();
for (int i = 0; i < orderByFields.size(); i++) {
String field = orderByFields.get(i).getField();
//第一个排序字段优先级最高,使用comparing
if (i == 0) {
dynamicComparator = Comparator.comparing((T x) ->
get(x, field), orderByFields.get(i).isAsc ? Comparator.naturalOrder() : Comparator.reverseOrder()
);
}else {
dynamicComparator = dynamicComparator.thenComparing((T x) ->
get(x, field), orderByFields.get(i).isAsc ? Comparator.naturalOrder() : Comparator.reverseOrder()
);
}
}
return dynamicComparator;
}
/**
* 反射获取值
* list<E> E非静态类时,可以把方法放入E对象中
* @param x
* @param field
* @return
*/
private static BigDecimal get(Object x, Object field) {
try {
String name = field.toString();
Field declaredField = x.getClass().getDeclaredField(name);
declaredField.setAccessible(true);
Object obj = declaredField.get(x);
//空值默认为最小值
if (obj == null) {
return BigDecimal.valueOf(Integer.MIN_VALUE);
}
if (declaredField.getType().equals(BigDecimal.class)) {
return new BigDecimal(obj.toString());
}
if (declaredField.getType().equals(LocalDate.class)) {
LocalDate result = (LocalDate) obj;
return BigDecimal.valueOf(result.atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli());
} else if (declaredField.getType().equals(Long.class)) {
return BigDecimal.valueOf((Long) obj);
} else {
return BigDecimal.valueOf(Integer.MIN_VALUE);
}
} catch (Exception e) {
log.error("失败", e);
}
return BigDecimal.valueOf(Integer.MIN_VALUE);
}
}
java8动态多字段排序内存排序模拟sql排序
最新推荐文章于 2024-04-26 10:18:14 发布