高校餐厅队列建模:Java优先级队列代码报错求助
解决Java PriorityQueue的ClassCastException问题
嘿,我来帮你搞定这个卡了好几天的问题!先直接说错误根源:你遇到的ClassCastException是因为你用了AbstractMap.SimpleEntry作为PriorityQueue的元素,但既没有给队列指定自定义比较器,这个Entry的默认排序逻辑也不符合你的需求,而且你明明已经写好了Customer类和CustomerComparator,却完全没用到它们——这才是核心问题!
问题拆解
- PriorityQueue排序逻辑缺失:你定义的
Queue<Map.Entry<Integer, Integer>> Restaurant = new PriorityQueue<>();没有传入比较器,队列会尝试把元素强制转成Comparable做自然排序,但AbstractMap.SimpleEntry的compareTo是先比key再比value的升序逻辑,和你需要的「年级优先级(Seniors>Juniors>sophomores>freshmen)」完全不符。 - 自定义Customer类未被使用:你已经封装了
Customer类来保存grade和到店时间,但代码里却用Map.Entry存数据,完全浪费了这个类的设计。 - grade生成逻辑有bug:你生成grade时误用了判断到客的
rand变量,而不是专门生成年级的rand2,导致grade的生成完全错误。 - 静态waitingTime的风险:把
waitingTime定义为静态变量,会导致多次调用方法或多线程场景下的状态混乱,应该改成局部变量。
修复后的完整代码
import java.util.*; // 修正比较器逻辑:grade越小优先级越高(1=Seniors优先级最高) class CustomerComparator implements Comparator<Customer> { @Override public int compare(Customer c1, Customer c2) { // 直接用Integer的compare方法,逻辑更简洁 return Integer.compare(c1.getGrade(), c2.getGrade()); } } class Customer { private int grade; private int arrivalTime; // 重命名为arrivalTime更贴合语义,记录顾客到店的分钟数 public Customer(int grade, int arrivalTime) { this.grade = grade; this.arrivalTime = arrivalTime; } public int getGrade() { return grade; } public int getArrivalTime() { return arrivalTime; } // 重写toString,方便调试时打印队列内容 @Override public String toString() { return String.format("(Grade:%d, Arrival:%d)", grade, arrivalTime); } } public class RestaurantPriority { // 改为Customer类型的PriorityQueue,并传入自定义比较器 private static Queue<Customer> restaurantQueue = new PriorityQueue<>(new CustomerComparator()); public static void main(String[] args) { simulateRestaurant(); } public static void simulateRestaurant() { int currentTime = 360; // 从早6点(第360分钟)开始 int orderProcessingTime = 0; // 改为局部变量,记录当前订单剩余处理时间 // 模拟营业时间:早6点到晚12点(第1440分钟) while (currentTime < 1440) { // 1. 处理当前订单的时间递减 if (orderProcessingTime > 0) { orderProcessingTime--; // 订单处理完成,取出队列下一位顾客并生成新的处理时间 if (orderProcessingTime == 0 && !restaurantQueue.isEmpty()) { restaurantQueue.poll(); orderProcessingTime = 2 + (int) (Math.random() * 6); // 生成2-7分钟的随机数 } } else if (!restaurantQueue.isEmpty()) { // 无正在处理的订单,但队列有顾客,开始处理第一位 orderProcessingTime = 2 + (int) (Math.random() * 6); } // 2. 判断是否有新顾客到店(每分钟20%概率) double arrivalChance = Math.random(); if (arrivalChance < 0.2) { // 生成顾客年级:四个年级各25%概率 double gradeChance = Math.random(); int grade; if (gradeChance < 0.25) { grade = 1; // Seniors } else if (gradeChance < 0.5) { grade = 2; // Juniors } else if (gradeChance < 0.75) { grade = 3; // sophomores } else { grade = 4; // freshmen } restaurantQueue.add(new Customer(grade, currentTime)); } // 3. 打印当前状态 System.out.printf("Time:%d, Remaining Process Time:%d, Queue:%s%n", currentTime, orderProcessingTime, restaurantQueue); currentTime++; } // 处理营业结束后剩余的顾客 System.out.println("=== 营业时间结束,处理剩余顾客 ==="); while (!restaurantQueue.isEmpty()) { if (orderProcessingTime == 0) { restaurantQueue.poll(); orderProcessingTime = 2 + (int) (Math.random() * 6); } orderProcessingTime--; System.out.printf("Time:%d, Remaining Process Time:%d, Queue:%s%n", currentTime, orderProcessingTime, restaurantQueue); currentTime++; } } }
关键修改点说明
- PriorityQueue类型修正:将队列改为
Queue<Customer>并传入CustomerComparator,确保队列按照年级优先级排序(grade越小优先级越高)。 - Customer类优化:重命名变量并添加
toString方法,让代码语义更清晰,调试更方便。 - 修复grade生成bug:改用专门的
gradeChance变量生成年级,逻辑正确。 - waitingTime改为局部变量:避免静态变量的状态污染,逻辑更严谨。
- 简化循环逻辑:将for循环改为while循环,处理营业结束后的剩余顾客更合理,避免原代码中i自增导致的循环异常。
现在运行这段代码,应该不会再出现ClassCastException,而且完全符合你的需求逻辑啦!
内容的提问来源于stack exchange,提问作者singularity
相关产品推荐
相关产品推荐

