Java PriorityQueue使用int[]与List<Integer>的行为差异排查
PriorityQueue<List> 版本代码失效原因
代码无法通过测试和PriorityQueue内部实现无关,是Java包装类的比较逻辑错误导致的:
- 原参考解法使用
int[]存储任务属性时,下标访问拿到的是基本类型int,==比较的是实际数值,排序逻辑正常。 - 替换为
List<Integer>后,get()返回的是Integer包装类对象,代码中a.get(2) == b.get(2)的写法是判断两个对象的内存引用是否一致,而非判断数值相等:- JVM默认仅缓存值在
[-128, 127]区间的Integer实例,该区间内相同值的Integer对象引用一致,==判断能返回正确结果 - 当任务处理时长、任务序号超过127时,相同数值的
Integer会生成不同对象实例,==判断会返回错误结果,直接导致优先级队列比较器逻辑错乱,排序结果不符合题目要求,自然无法通过测试。
另外代码中两处使用a.getXxx() - b.getXxx()返回比较结果的写法存在整数溢出风险,极端场景下也会导致排序错误。
- JVM默认仅缓存值在
修复方法
将所有涉及Integer比较的逻辑改为基于数值的比较,避免引用判断和溢出问题,核心修改点如下:
- 修正任务列表按入队时间排序的比较器
- 修正优先级队列的比较器,替换
==判断为数值比较,同时规避整数溢出 - 删除代码末尾多余的类闭合花括号
修复后的完整可运行代码:
public int[] getOrder(int[][] tasks) { int n = tasks.length; // 构造带序号的扩展任务列表 List<List<Integer>> extendedTask = new LinkedList<>(); for(int i = 0; i < tasks.length; i++) { extendedTask.add(Stream.of(i, tasks[i][0], tasks[i][1]).collect(Collectors.toList())); } // 按入队时间排序,使用Integer.compare避免溢出 extendedTask.sort((a, b) -> Integer.compare(a.get(1), b.get(1))); // 优先级队列:先按处理时长升序,时长相同按任务序号升序 PriorityQueue<List<Integer>> pq = new PriorityQueue<>((a,b) -> { int processTimeCmp = Integer.compare(a.get(2), b.get(2)); return processTimeCmp != 0 ? processTimeCmp : Integer.compare(a.get(0), b.get(0)); }); int[] res = new int[tasks.length]; int idx = 0; long currentTime = 0; int currentTimeIdx = 0; while(idx < n) { // 将所有入队时间小于等于当前时间的任务加入队列 while(currentTimeIdx < n && extendedTask.get(currentTimeIdx).get(1) <= currentTime) { pq.offer(extendedTask.get(currentTimeIdx++)); } if(pq.isEmpty()) { // 队列为空时直接跳转到下一个任务的入队时间 currentTime = extendedTask.get(currentTimeIdx).get(1); continue; } // 取出优先级最高的任务执行 List<Integer> curr = pq.poll(); res[idx++] = curr.get(0); currentTime += curr.get(2); } return res; }
内容的提问来源于stack exchange,提问作者yoel
相关产品推荐
相关产品推荐

