【发布时间】:2015-04-10 16:30:38
【问题描述】:
意图
实现一个任务队列,排序基于 1) 优先级和 2) 时间,特别是任务创建时间或时间戳(未插入队列),优先考虑时间戳较旧的任务。
试过
这是我目前得到的;比我想象的要简单得多,因为它需要的不仅仅是一个 PriorityQueue。在比较器中,如果两个优先级相等,则对Task.time进行另一次比较,否则仅根据Task.priority进行比较。
import java.util.Comparator;
import java.util.PriorityQueue;
public class QueueWithPriorityAndTimeSort {
enum TaskPriority {
High, Medium, Low
}
class Task implements Comparable<Task> {
long time;
TaskPriority priority;
Task(TaskPriority p, long t) {
time = t;
priority = p;
}
public int compareTo(Task task2) {
return priority.compareTo(task2.priority);
}
}
class HighPriorityWithTimeComparator implements Comparator<Task> {
public int compare(Task task1, Task task2) {
int compareResult = task1.compareTo(task2);
if( compareResult == 0){
//same priority, now compare on time
if( task2.time < task1.time)
compareResult = 1;
else
compareResult = -1;
}
return compareResult;
}
}
public void buildAndTestQueue(){
PriorityQueue<Task> queue =
new PriorityQueue<Task>(3, new HighPriorityWithTimeComparator());
queue.add(new Task(TaskPriority.High, 9));
queue.add(new Task(TaskPriority.Low, 7));
queue.add(new Task(TaskPriority.Low, 3));
queue.add(new Task(TaskPriority.High, 2));
queue.add(new Task(TaskPriority.Medium, 5));
queue.add(new Task(TaskPriority.Medium, 4));
queue.add(new Task(TaskPriority.High, 6));
queue.add(new Task(TaskPriority.High, 8));
queue.add(new Task(TaskPriority.Low, 15));
queue.add(new Task(TaskPriority.Low, 10));
Task m = null;
while ((m = queue.poll()) != null)
System.out.println(
String.format("Priority: %s, %d", m.priority, m.time));
}
public static void main(String args[]) {
QueueWithPriorityAndTimeSort queueTest =
new QueueWithPriorityAndTimeSort();
queueTest.buildAndTestQueue();
}
}
问题
这是一种有效的方法吗?我不相信添加的比较器逻辑会改变时间复杂度;除此之外,我没有看到任何明显的问题。
【问题讨论】:
-
是的,这是正确的方法。您可以使用
Long.compare()来比较您的时间。您可以将您的 main 方法转换为适当的单元测试,以检查一切是否按预期工作。 -
当然,这是一种有效的方法。唯一对我来说有点奇怪的是比较逻辑是如何在 Task 中的 compareTo 实现和外部比较器之间拆分的。为什么不把所有的比较逻辑放在一个或另一个中呢?自从我使用 PriorityQueue 已经有一段时间了,但是如果您的值类型实现 Comparable,那么 iirc PQ 将正常工作(即不提供 Comparator)。
-
我很好奇,当您可以实现 Comparator 内部的所有逻辑时,为什么还要使用 Comparable 和 Comparator?
-
@wdf 考虑了自己,并决定根据上下文和用途拆分逻辑。基于优先级和时间的比较仅在
Tasks 驻留在队列中时才相关,否则,时间并不那么重要。分离这些关注点允许根据特定需求进行排序以提高灵活性。 -
@raffian 这似乎有点过头了。但由于您的目标是拥有灵活的排序算法,请参阅我的答案。
标签: java queue priority-queue