如何在Java问题追踪器项目中使用Comparator与Priority Queue实现按优先级或时间戳展示问题
嘿,我来帮你搞定这个需求!用PriorityQueue结合Comparator完全可以实现按优先级或创建时间排序展示你的Issue,下面一步步给你拆解清楚:
1. 核心思路
PriorityQueue默认会按照元素的自然排序规则排列,但咱们的Issue需要自定义排序逻辑(优先级或创建时间),这时候就可以用Comparator来指定排序规则,把它传给PriorityQueue的构造方法,队列就会自动按照咱们设定的规则对Issue进行排序,之后从队列里取元素的时候,拿到的就是有序的结果啦。
2. 实现按优先级排序的逻辑
首先,你提到优先级是1-9的数字,通常咱们会认为1是最高优先级(如果你的需求是9最高,后面我会说怎么调整)。咱们先写一个Comparator来实现按优先级从小到大排序(也就是高优先级在前):
import java.util.Comparator; // 按优先级排序的比较器 public class PriorityComparator implements Comparator<Issue> { @Override public int compare(Issue issue1, Issue issue2) { // 优先级小的排前面(1最高) return Integer.compare(issue1.priority, issue2.priority); // 如果要让9是最高优先级,就反过来写: // return Integer.compare(issue2.priority, issue1.priority); } }
3. 实现按创建时间排序的逻辑
你的Issue类里已经有了TimeStamp字段(创建时自动赋值为当前时间),Date类型本身支持比较,所以咱们可以直接基于这个字段写比较器:
// 按创建时间排序的比较器 public class TimeStampComparator implements Comparator<Issue> { @Override public int compare(Issue issue1, Issue issue2) { // 按创建时间从早到晚排序(最早创建的在前) return issue1.TimeStamp.compareTo(issue2.TimeStamp); // 如果要最新创建的在前,就反过来: // return issue2.TimeStamp.compareTo(issue1.TimeStamp); } }
4. 实际使用示例
为了方便创建Issue对象,我给你的Issue类加了一个构造方法(不然每次手动赋值太麻烦),然后写个Demo演示怎么用这两个比较器:
import java.util.Date; import java.util.PriorityQueue; public class IssueTrackerDemo { public static void main(String[] args) { // 1. 创建按优先级排序的队列 PriorityQueue<Issue> prioritySortedQueue = new PriorityQueue<>(new PriorityComparator()); // 添加几个测试Issue prioritySortedQueue.add(new Issue(1, "登录功能BUG", "用户输入正确密码仍无法登录", "张三", "李四", "BUG", 1, "OPEN")); prioritySortedQueue.add(new Issue(2, "界面按钮优化", "提交按钮样式与整体风格不符", "王五", "赵六", "UI", 3, "OPEN")); prioritySortedQueue.add(new Issue(3, "系统性能问题", "首页加载耗时超过5秒", "张三", "李四", "PERF", 2, "OPEN")); // 输出按优先级排序的结果 System.out.println("=== 按优先级排序的问题 ==="); while (!prioritySortedQueue.isEmpty()) { Issue issue = prioritySortedQueue.poll(); System.out.printf("编号:%d | 标题:%s | 优先级:%d%n", issue.IssueNo, issue.IssueTitle, issue.priority); } // 2. 创建按创建时间排序的队列 PriorityQueue<Issue> timeSortedQueue = new PriorityQueue<>(new TimeStampComparator()); // 模拟不同时间创建的Issue(用Thread.sleep来错开时间) Issue issueA = new Issue(4, "数据库连接失败", "连接超时,无法访问数据库", "钱七", "孙八", "DB", 2, "OPEN"); try { Thread.sleep(1000); // 等待1秒,模拟时间差 } catch (InterruptedException e) { e.printStackTrace(); } Issue issueB = new Issue(5, "API返回错误", "调用用户信息接口返回500", "周九", "吴十", "API", 1, "OPEN"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Issue issueC = new Issue(6, "文档缺失", "支付接口文档未说明参数必填项", "郑十一", "王十二", "DOC", 3, "OPEN"); timeSortedQueue.add(issueA); timeSortedQueue.add(issueB); timeSortedQueue.add(issueC); // 输出按创建时间排序的结果 System.out.println("\n=== 按创建时间排序的问题 ==="); while (!timeSortedQueue.isEmpty()) { Issue issue = timeSortedQueue.poll(); System.out.printf("编号:%d | 标题:%s | 创建时间:%s%n", issue.IssueNo, issue.IssueTitle, issue.TimeStamp); } } } // 补充了构造方法的Issue类 class Issue { int IssueNo; String IssueTitle; String text; Date TimeStamp = new Date(); String Creator; String Assignee; String tag; int priority; String status; // 构造方法,方便快速创建Issue对象 public Issue(int issueNo, String issueTitle, String text, String creator, String assignee, String tag, int priority, String status) { IssueNo = issueNo; IssueTitle = issueTitle; this.text = text; Creator = creator; Assignee = assignee; this.tag = tag; this.priority = priority; this.status = status; } }
5. 简化写法:用Lambda表达式替代单独的Comparator类
如果不想写单独的Comparator类,咱们可以用Lambda表达式简化代码,这样更清爽:
// 按优先级排序的队列(Lambda版) PriorityQueue<Issue> priorityQueue = new PriorityQueue<>((i1, i2) -> Integer.compare(i1.priority, i2.priority)); // 按创建时间排序的队列(Lambda版) PriorityQueue<Issue> timeQueue = new PriorityQueue<>((i1, i2) -> i1.TimeStamp.compareTo(i2.TimeStamp));
几个小提醒
- PriorityQueue是非线程安全的,如果你的程序是多线程环境,建议用
PriorityBlockingQueue(属于java.util.concurrent包)。 - 每次调用
poll()方法会取出队列的头部元素(也就是排序后的第一个元素),取完后队列会自动调整内部顺序,保证下一次取的还是符合规则的元素。 - 排序逻辑完全可以根据你的需求调整,比如优先级的高低顺序、时间的正序倒序,只要修改compare方法里的参数顺序就行。
内容的提问来源于stack exchange,提问作者Saad Hamim
相关产品推荐
相关产品推荐

