优先级计算

parent aba10b46
package com.aps.entity.Algorithm;
import lombok.Data;
import java.util.List;
@Data
public class OrderSortRule {
private boolean enabled;
private List<SortCondition> conditions;
@Data
public static class SortCondition {
private int sequence;
private String fieldName;
private boolean reverse;
private String customComparator;
}
}
\ No newline at end of file
...@@ -21,5 +21,6 @@ public class Order { ...@@ -21,5 +21,6 @@ public class Order {
private int priority; private int priority;
private boolean canSplit = false; private boolean canSplit = false;
private boolean canInterrupt = false; private boolean canInterrupt = false;
private double actualPriority;
} }
\ No newline at end of file
package com.aps.service.Algorithm;
import com.aps.entity.Algorithm.OrderSortRule;
import com.aps.entity.basic.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 增强版订单排序服务(结合配置化排序器)
* 支持基于配置规则的动态排序和优先级分配
*/
@Slf4j
@Service
public class OrderSortService {
// 默认优先级基数
private static final double DEFAULT_BASE_PRIORITY = 1.0;
// 默认优先级范围
private static final double DEFAULT_LEVEL_RANGE = 1.0;
// 字段提取器映射(静态常量,所有实例共享)
private static final Map<String, Function<Order, ?>> FIELD_EXTRACTORS = new HashMap<>();
/**
* 初始化字段提取器(使用Spring的PostConstruct)
*/
@PostConstruct
public void initializeFieldExtractors() {
registerFieldExtractor("id", Order::getId);
registerFieldExtractor("productId", Order::getProductId);
registerFieldExtractor("quantity", Order::getQuantity);
registerFieldExtractor("dueDate", Order::getDueDate);
registerFieldExtractor("priority", Order::getPriority);
registerFieldExtractor("tardiness", Order::getTardiness);
registerFieldExtractor("canSplit", Order::isCanSplit);
registerFieldExtractor("canInterrupt", Order::isCanInterrupt);
// 可以在这里加载扩展的字段提取器
}
/**
* 注册字段提取器(统一处理字段名小写)
*/
private void registerFieldExtractor(String fieldName, Function<Order, ?> extractor) {
FIELD_EXTRACTORS.put(fieldName.toLowerCase(), extractor);
}
/**
* 分配优先级(更新原列表)
*/
public void assignPriority(List<Order> orders, OrderSortRule rule) {
Objects.requireNonNull(orders, "Orders list must not be null");
Objects.requireNonNull(rule, "Sort rule must not be null");
if (CollectionUtils.isEmpty(orders)) {
return;
}
List<Order> sortedOrders = assignPriorityValues(new ArrayList<>(orders), rule);
// 更新原列表
orders.clear();
orders.addAll(sortedOrders);
}
/**
* 根据数据库配置的规则对订单排序
*/
public List<Order> sortByRule(List<Order> orders, OrderSortRule rule) {
Objects.requireNonNull(orders, "Orders list must not be null");
Objects.requireNonNull(rule, "Sort rule must not be null");
if (CollectionUtils.isEmpty(orders)) {
return new ArrayList<>();
}
if (rule == null || !rule.isEnabled() || CollectionUtils.isEmpty(rule.getConditions())) {
return new ArrayList<>(orders);
}
// 按条件顺序排序
List<OrderSortRule.SortCondition> sortedConditions = rule.getConditions().stream()
.sorted(Comparator.comparingInt(OrderSortRule.SortCondition::getSequence))
.collect(Collectors.toList());
// 构建比较器链
Comparator<Order> comparator = null;
for (OrderSortRule.SortCondition condition : sortedConditions) {
Comparator<Order> currentComparator = createConditionComparator(condition);
if (comparator == null) {
comparator = currentComparator;
} else {
comparator = comparator.thenComparing(currentComparator);
}
}
return orders.stream()
.sorted(comparator != null ? comparator : Comparator.comparing(Order::getId))
.collect(Collectors.toList());
}
/**
* 分配多级优先级数值
*/
public List<Order> assignPriorityValues(List<Order> orders, OrderSortRule rule) {
Objects.requireNonNull(orders, "Orders list must not be null");
Objects.requireNonNull(rule, "Sort rule must not be null");
if (CollectionUtils.isEmpty(orders)) {
return new ArrayList<>();
}
if (rule == null || !rule.isEnabled() || CollectionUtils.isEmpty(rule.getConditions())) {
return new ArrayList<>(orders);
}
List<OrderSortRule.SortCondition> sortedConditions = rule.getConditions().stream()
.sorted(Comparator.comparingInt(OrderSortRule.SortCondition::getSequence))
.collect(Collectors.toList());
// 递归分配优先级
assignPriorityRecursive(orders, sortedConditions, 0, DEFAULT_BASE_PRIORITY, DEFAULT_LEVEL_RANGE);
// 按优先级排序
return orders.stream()
.sorted(Comparator.comparingDouble(Order::getPriority))
.collect(Collectors.toList());
}
/**
* 递归分配优先级
*/
private void assignPriorityRecursive(List<Order> orders,
List<OrderSortRule.SortCondition> conditions,
int conditionIndex,
double basePriority,
double levelRange) {
if (conditionIndex >= conditions.size() || CollectionUtils.isEmpty(orders)) {
return;
}
OrderSortRule.SortCondition currentCondition = conditions.get(conditionIndex);
Function<Order, ?> keyExtractor = getFieldExtractor(currentCondition.getFieldName());
if (keyExtractor == null) {
// 跳过无效字段,处理下一个条件
assignPriorityRecursive(orders, conditions, conditionIndex + 1, basePriority, levelRange);
return;
}
// 按当前条件分组
Map<Object, List<Order>> groups = orders.stream()
.collect(Collectors.groupingBy(keyExtractor));
// 对分组键排序
List<Object> sortedKeys = getSortedKeys(groups, currentCondition);
double groupIncrement = levelRange / groups.size();
for (int i = 0; i < sortedKeys.size(); i++) {
List<Order> group = groups.get(sortedKeys.get(i));
double groupPriority = basePriority + i * groupIncrement;
if (conditionIndex == conditions.size() - 1) {
// 最后一级条件,直接分配优先级
assignPriorityToGroup(group, groupPriority, groupIncrement);
} else {
// 递归处理下一级
assignPriorityRecursive(group, conditions, conditionIndex + 1,
groupPriority, groupIncrement);
}
}
}
/**
* 为组内订单分配优先级
*/
private void assignPriorityToGroup(List<Order> orders, double basePriority, double range) {
if (CollectionUtils.isEmpty(orders)) {
return;
}
double increment = range / orders.size();
for (int i = 0; i < orders.size(); i++) {
Order order = orders.get(i);
double priority = basePriority + i * increment;
order.setActualPriority(priority);
}
}
/**
* 创建单个条件的比较器
*/
@SuppressWarnings("unchecked")
private Comparator<Order> createConditionComparator(OrderSortRule.SortCondition condition) {
Objects.requireNonNull(condition, "Sort condition must not be null");
Function<Order, ?> keyExtractor = getFieldExtractor(condition.getFieldName());
if (keyExtractor == null) {
log.warn("No field extractor found for field: {}, using default id comparator",
condition.getFieldName());
return Comparator.comparing(Order::getId);
}
Comparator<Object> fieldComparator = getFieldComparator(condition);
Comparator<Order> comparator = (Comparator<Order>) Comparator.comparing(keyExtractor, fieldComparator);
return condition.isReverse() ? comparator.reversed() : comparator;
}
/**
* 获取字段提取器
*/
private Function<Order, ?> getFieldExtractor(String fieldName) {
if (fieldName == null) {
return null;
}
return FIELD_EXTRACTORS.get(fieldName.toLowerCase());
}
/**
* 获取字段比较器
*/
@SuppressWarnings("unchecked")
private Comparator<Object> getFieldComparator(OrderSortRule.SortCondition condition) {
Objects.requireNonNull(condition, "Sort condition must not be null");
// 尝试使用自定义比较器
if (condition.getCustomComparator() != null && !condition.getCustomComparator().isEmpty()) {
try {
Class<?> clazz = Class.forName(condition.getCustomComparator());
Method method = clazz.getMethod("getInstance");
return (Comparator<Object>) method.invoke(null);
} catch (ClassNotFoundException e) {
log.error("Custom comparator class not found: {}", condition.getCustomComparator(), e);
} catch (NoSuchMethodException e) {
log.error("Custom comparator class {} must have static getInstance() method",
condition.getCustomComparator(), e);
} catch (Exception e) {
log.error("Failed to instantiate custom comparator: {}", condition.getCustomComparator(), e);
}
}
// 根据字段类型返回默认比较器
Function<Order, ?> extractor = getFieldExtractor(condition.getFieldName());
if (extractor == null) {
return Comparator.comparing(Object::toString);
}
// 使用示例订单获取类型信息(如果有订单)
try {
// 尝试创建示例对象或使用更安全的类型推断
Order sample = new Order();
Object sampleValue = extractor.apply(sample);
if (sampleValue instanceof Integer) {
return (Comparator<Object>) Comparator.comparingInt(o -> (Integer) o);
} else if (sampleValue instanceof Long) {
return (Comparator<Object>) Comparator.comparingLong(o -> (Long) o);
} else if (sampleValue instanceof Double) {
return (Comparator<Object>) Comparator.comparingDouble(o -> (Double) o);
} else if (sampleValue instanceof OffsetDateTime) {
return (Comparator<Object>) Comparator.comparing(o -> (OffsetDateTime) o);
} else if (sampleValue instanceof Boolean) {
return (Comparator<Object>) Comparator.comparing(o -> (Boolean) o);
}
} catch (Exception e) {
log.debug("Failed to determine field type for comparator, using default string comparator", e);
}
return Comparator.comparing(Object::toString);
}
/**
* 获取排序后的分组键
*/
private List<Object> getSortedKeys(Map<Object, List<Order>> groups,
OrderSortRule.SortCondition condition) {
Objects.requireNonNull(groups, "Groups map must not be null");
Objects.requireNonNull(condition, "Sort condition must not be null");
Comparator<Object> comparator = getFieldComparator(condition);
return groups.keySet().stream()
.sorted(condition.isReverse() ? comparator.reversed() : comparator)
.collect(Collectors.toList());
}
}
\ No newline at end of file
package com.aps.demo;
import com.aps.entity.Algorithm.OrderSortRule;
import com.aps.entity.basic.Order;
import com.aps.service.Algorithm.OrderSortService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
/**
* 订单排序服务测试类
*/
@ExtendWith(MockitoExtension.class)
class OrderSortServiceTest {
@InjectMocks
private OrderSortService orderSortService;
private List<Order> testOrders;
@BeforeEach
void setUp() {
// 初始化服务(触发@PostConstruct)
orderSortService.initializeFieldExtractors();
// 创建测试数据
testOrders = createTestOrders();
}
@Test
void testAssignPriority_WithMultipleConditions() {
// 创建多条件排序规则:先按dueDate,再按priority
OrderSortRule rule = createMultiConditionRule();
// 执行测试
orderSortService.assignPriority(testOrders, rule);
// 验证多级优先级分配
printOrderPriorities(testOrders); // 调试输出
}
/**
* 创建测试订单数据
*/
private List<Order> createTestOrders() {
List<Order> orders = new ArrayList<>();
// 创建5个测试订单,具有不同的属性
for (int i = 1; i <= 5; i++) {
Order order = new Order();
order.setId(i);
order.setProductId(100 + i);
order.setQuantity(50.0 * i);
order.setPriority(6 - i); // 优先级:5,4,3,2,1(倒序)
order.setDueDate(OffsetDateTime.now().plusDays(i)); // 到期日递增
order.setTardiness(i * 0.5);
order.setCanSplit(i % 2 == 0);
order.setCanInterrupt(i % 3 == 0);
orders.add(order);
}
return orders;
}
/**
* 创建多条件排序规则
*/
private OrderSortRule createMultiConditionRule() {
OrderSortRule rule = new OrderSortRule();
rule.setEnabled(true);
List<OrderSortRule.SortCondition> conditions = new ArrayList<>();
// 条件1:按是否可拆分
OrderSortRule.SortCondition condition1 = new OrderSortRule.SortCondition();
condition1.setSequence(1);
condition1.setFieldName("canSplit");
condition1.setReverse(true); // 可拆分的在前
conditions.add(condition1);
// 条件2:按到期日
OrderSortRule.SortCondition condition2 = new OrderSortRule.SortCondition();
condition2.setSequence(2);
condition2.setFieldName("dueDate");
condition2.setReverse(false); // 早到期在前
conditions.add(condition2);
// 条件3:按优先级
OrderSortRule.SortCondition condition3 = new OrderSortRule.SortCondition();
condition3.setSequence(3);
condition3.setFieldName("priority");
condition3.setReverse(true); // 高优先级在前
conditions.add(condition3);
rule.setConditions(conditions);
return rule;
}
/**
* 打印订单优先级(用于调试)
*/
private void printOrderPriorities(List<Order> orders) {
System.out.println("=== 订单优先级分配结果 ===");
for (Order order : orders) {
System.out.printf("订单ID: %d, 优先级: %.4f, 到期日: %s, 原优先级: %d, 可拆分: %s%n",
order.getId(), order.getActualPriority(),
order.getDueDate(), order.getPriority(), order.isCanSplit());
}
System.out.println("========================");
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment