Java compareTo 方法失败
Java compareTo method fails
我有一个名为 class 的任务,我想将其放入 PriorityQueue。
我的 class 可与 日期 和一个名为 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}
我在 compareTo 方法中做错了什么?
return x + date.compareTo(task.date)
你没有给你的 urgent
标志足够的权重。
如果x
为-1,日期比较的结果为1,则return归零。
此外,不能保证日期比较会 return -1、0 或 1(即使初步测试指出确实如此)。 Javadoc 只是声明:
Returns:
the value 0 if the argument Date
is equal to this Date
; a value less than 0 if this Date
is before the Date
argument; and a
value greater than 0 if this Date
is after the Date
argument.
一个简单的解决方法是:
@Override
public int compareTo(Task task) {
if (!isUrgent && task.isUrgent)
return 1;
else if (isUrgent && !task.isUrgent)
return -1;
return date.compareTo(task.date);
}
您似乎想要的是先按紧急程度比较任务,然后再按日期进行比较。您不应将两个比较器的结果相加,而应将结果链接起来,以便仅在两个任务的紧急程度相同时才比较它们的日期(即,两者都是紧急的,或者都是非紧急的)。
幸运的是,Comparator
class 有一些有用的方法,可以轻松创建一个满足您需要的比较器。大多数时候,包括在您的用例中,您不需要实际编写自己的 compareTo
方法。您可以使用 comparing
method to compare by urgency or date, and you can use thenComparing
to chain them together. The reversed
方法来比较紧急程度,以便 true
发生在 false
之前。
Comparator<Task> cmp =
Comparator.comparing(t -> t.isUrgent).reversed().thenComparing(t -> t.date);
或者使用方法引用(如果你的 class 有 getter 方法):
Comparator<Task> cmp =
Comparator.comparing(Task::isUrgent).reversed().thenComparing(Task::getDate);
然后您可以通过调用适当的 PriorityQueue
constructor:
创建一个使用此比较器的优先级队列
PriorityQueue<Task> queue = new PriorityQueue<>(cmp);
我有一个名为 class 的任务,我想将其放入 PriorityQueue。
我的 class 可与 日期 和一个名为 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}
我在 compareTo 方法中做错了什么?
return x + date.compareTo(task.date)
你没有给你的 urgent
标志足够的权重。
如果x
为-1,日期比较的结果为1,则return归零。
此外,不能保证日期比较会 return -1、0 或 1(即使初步测试指出确实如此)。 Javadoc 只是声明:
Returns:
the value 0 if the argumentDate
is equal to thisDate
; a value less than 0 if thisDate
is before theDate
argument; and a value greater than 0 if thisDate
is after theDate
argument.
一个简单的解决方法是:
@Override
public int compareTo(Task task) {
if (!isUrgent && task.isUrgent)
return 1;
else if (isUrgent && !task.isUrgent)
return -1;
return date.compareTo(task.date);
}
您似乎想要的是先按紧急程度比较任务,然后再按日期进行比较。您不应将两个比较器的结果相加,而应将结果链接起来,以便仅在两个任务的紧急程度相同时才比较它们的日期(即,两者都是紧急的,或者都是非紧急的)。
幸运的是,Comparator
class 有一些有用的方法,可以轻松创建一个满足您需要的比较器。大多数时候,包括在您的用例中,您不需要实际编写自己的 compareTo
方法。您可以使用 comparing
method to compare by urgency or date, and you can use thenComparing
to chain them together. The reversed
方法来比较紧急程度,以便 true
发生在 false
之前。
Comparator<Task> cmp =
Comparator.comparing(t -> t.isUrgent).reversed().thenComparing(t -> t.date);
或者使用方法引用(如果你的 class 有 getter 方法):
Comparator<Task> cmp =
Comparator.comparing(Task::isUrgent).reversed().thenComparing(Task::getDate);
然后您可以通过调用适当的 PriorityQueue
constructor:
PriorityQueue<Task> queue = new PriorityQueue<>(cmp);