You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义对象的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,直到循环结束都无法正确显示进度。

修复方案

  1. 修正compareTo方法:如果使用默认自然排序,改成正确的比较逻辑:
@Override
public int compareTo(JobNode o) {
    // 小优先级在前(数字越小优先级越高)
    return Integer.compare(this.priority, o.priority);
    // 若要大优先级在前,改为:return Integer.compare(o.priority, this.priority);
}
  1. 启用自定义比较器:如果想用jobCompare的逻辑(大优先级在前),初始化队列时传入比较器:
PriorityQueue<JobNode> jobQueue = new PriorityQueue<>(new jobCompare());
  1. 合并打印与处理逻辑:避免队列被提前取空,同时修正进度计算:
// 打印并处理任务
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 14:40:28