自定义对象的Priority Queue/Comparator无法正常工作求助
问题分析与解决
我知道这个问题已经被问过多次,但查阅所有解答后,我认为问题并非出在迭代时使用poll(),而是我的比较逻辑可能存在问题。每次尝试打印元素时,它们都呈随机顺序。我了解Priority Queue内部是树结构,最小元素为根节点,本以为通过poll()迭代能解决问题,但并未奏效(此前我还尝试过remove和自定义迭代器)。我怀疑比较逻辑存在问题,附上我的代码:
import java.util.Arrays; import java.util.Comparator; import java.util.PriorityQueue; import java.util.Scanner; import java.util.Iterator; public class scheduleCPU { public static void main(String[] args) { jobCompare compare = new jobCompare(); PriorityQueue<JobNode> jobQueue = new PriorityQueue<>(); // 创建任务节点队列 int pJob = 0; String nJob = null; int lJob = 0; Scanner userInput = new Scanner(System.in); // 创建Scanner对象 Boolean exitInput = false; // 输入任务信息 while(exitInput != true) { System.out.println("输入任务优先级、时长和名称,输入101停止添加任务"); pJob = userInput.nextInt(); if(pJob ==101) { userInput.close(); break; } lJob = userInput.nextInt(); nJob = userInput.next(); JobNode currentJob = new JobNode(pJob, nJob, lJob); jobQueue.add(currentJob); } Iterator<JobNode> jobIt = jobQueue.iterator(); // 打印任务 while(!jobQueue.isEmpty()) { // Arrays.sort(jobQueue.toArray()); JobNode currentJob = jobQueue.poll(); System.out.println(currentJob.name); // System.out.println(jobQueue); } // 处理任务 while(jobQueue.size()>0) { JobNode current = jobQueue.remove(); int jobLength = current.length; for(int i =0; i<jobLength;i++) { System.out.println("Job"+ current.name + " is " + ((i/jobLength)*100) + "% complete"); } } } } class JobNode implements Comparable<JobNode> { int priority; String name; int length; // 构造方法 JobNode(int p, String n, int l) { priority = p; name = n; length = l; } @Override public int compareTo(JobNode o) { return this.priority; } } class jobCompare implements Comparator<JobNode> { @Override public int compare(JobNode j1, JobNode j2) { if (j1.priority < j2.priority) return 1; else if (j1.priority > j2.priority) return -1; return 0; } }
问题根源
compareTo方法逻辑错误:JobNode实现的Comparable接口中,compareTo直接返回this.priority,完全不符合比较逻辑。正确的比较应该返回当前对象与目标对象的优先级差值(或使用Integer.compare),否则PriorityQueue无法正确维护堆结构,自然无法按预期顺序取出元素。- 自定义比较器未被使用:你创建了
jobCompare比较器,但初始化PriorityQueue时没有传入该比较器,导致队列默认使用逻辑错误的compareTo方法。 - 队列元素被提前取空:第一个
while循环用poll()取出了所有元素并打印,第二个处理任务的循环执行时队列已为空,无法执行任务处理逻辑。 - 进度百分比计算错误:原代码中
(i/jobLength)*100因整数除法会一直返回0,直到循环结束都无法正确显示进度。
修复方案
- 修正
compareTo方法:如果使用默认自然排序,改成正确的比较逻辑:
@Override public int compareTo(JobNode o) { // 小优先级在前(数字越小优先级越高) return Integer.compare(this.priority, o.priority); // 若要大优先级在前,改为:return Integer.compare(o.priority, this.priority); }
- 启用自定义比较器:如果想用
jobCompare的逻辑(大优先级在前),初始化队列时传入比较器:
PriorityQueue<JobNode> jobQueue = new PriorityQueue<>(new jobCompare());
- 合并打印与处理逻辑:避免队列被提前取空,同时修正进度计算:
// 打印并处理任务 while(!jobQueue.isEmpty()) { JobNode currentJob = jobQueue.poll(); System.out.println("开始处理任务:" + currentJob.name); int jobLength = currentJob.length; for(int i = 1; i <= jobLength; i++) { // 先乘100再做除法,避免整数除法导致的0值问题 System.out.println("Job " + currentJob.name + " is " + ((i * 100) / jobLength) + "% complete"); } System.out.println("任务 " + currentJob.name + " 处理完成"); }
内容的提问来源于stack exchange,提问作者JG98
相关产品推荐
相关产品推荐

