Java compareTo 方法失败



我有一个名为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;如果参数 如果此DateDate参数之后,则值大于 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);
}

最新更新