我有一个名为task的类,我想在PriorityQueue中获取它。
我的类按日期和一个名为isUrgent的布尔字段可比
@Override
public int compareTo(Task task) {
int x = 0;
if (!isUrgent && task.isUrgent)
x=1;
else if (isUrgent && !task.isUrgent)
x=-1;
else return date.compareTo(task.date);
return x +date.compareTo(task.date);
}
第一次使用 Comparables,当我从优先级队列中删除任务时,它应该在最近的日期之前删除,但如果它是紧急的,那么它应该被删除第一个紧急任务。
但我在删除过程中得到了这个,
Task{isUrgent=true, date=Sat Apr 04 00:00:00 BST 2020}
Task{isUrgent=true, date=Sat Apr 04 00:00:00 BST 2020}
Task{isUrgent=false, date=Sat Apr 04 00:00:00 BST 2020}
Task{isUrgent=true, date=Thu Apr 04 00:00:00 BST 2030}
Task{isUrgent=false, date=Sat Apr 04 00:00:00 BST 2020}
Task{isUrgent=true, date=Thu Apr 04 00:00:00 BST 2030}
Task{isUrgent=false, date=Thu Apr 04 00:00:00 BST 2030}
Task{isUrgent=false, date=Thu Apr 04 00:00:00 BST 2030}
我在比较方法中做错了什么?
您似乎想要的是先按紧急程度比较任务,然后按日期比较任务。您应该链接结果,而不是添加两个比较器的结果,以便仅在两个任务的紧急程度相同(即两者都是紧急的或都是非紧急的(时才比较它们的日期。
幸运的是,Comparator
类有一些有用的方法,可以轻松创建执行所需操作的比较器。大多数时候,包括在你的用例中,你不需要实际编写自己的compareTo
方法。您可以使用comparing
方法按紧急程度或日期进行比较,也可以使用thenComparing
将它们链接在一起。reversed
方法允许您比较紧急性,以便在false
之前发生true
。
Comparator<Task> cmp =
Comparator.comparing(t -> t.isUrgent).reversed().thenComparing(t -> t.date);
或者使用方法引用(如果你的类有 getter 方法(:
Comparator<Task> cmp =
Comparator.comparing(Task::isUrgent).reversed().thenComparing(Task::getDate);
然后,您可以通过调用相应的PriorityQueue
构造函数来创建使用此比较器的优先级队列:
PriorityQueue<Task> queue = new PriorityQueue<>(cmp);
返回x + date.compareTo(task.date)
,您没有给予urgent
旗足够的权重。
如果x
为 -1,并且日期比较的结果为 1,则将返回零。
此外,不能保证日期比较将返回 -1、0 或 1(即使初步测试指出它确实如此(。Javadoc只是说:
返回:
如果参数Date
等于此Date
,则值为 0;如果此Date
参数在Date
参数之前,则值小于 0;如果参数 如果此Date
在Date
参数之后,则值大于 0。
一个简单的解决方法是:
@Override
public int compareTo(Task task) {
if (!isUrgent && task.isUrgent)
return 1;
else if (isUrgent && !task.isUrgent)
return -1;
return date.compareTo(task.date);
}