On compareTo
合同
问题出在你的compareTo
。这是摘录自文档 http://download.oracle.com/javase/6/docs/api/java/lang/Comparable.html:
实施者必须确保sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
对全部x
and y
.
此处转载您的原始代码以供参考:
// original compareTo implementation with bug marked
@Override
public int compareTo(Object o) {
int output = 0;
if (boeking.compareTo(((Ticket) o).getBoeking())==0)
{
if(this.equals(o))
{
return output;
}
else return 1; // BUG!!!! See explanation below!
}
else output = boeking.compareTo(((Ticket) o).getBoeking());
return output;
}
为什么是return 1;
一个错误?考虑以下场景:
- Given
Ticket t1, t2
- Given
t1.boeking.compareTo(t2.boeking) == 0
- Given
t1.equals(t2)
return false
- Now we have both of the following:
-
t1.compareTo(t2)
回报1
-
t2.compareTo(t1)
回报1
最后一个结果是违反 of the compareTo
合同。
解决问题
首先也是最重要的一点,你应该利用以下事实:Comparable<T>
是一个可参数化的泛型类型。也就是说,而不是:
// original declaration; uses raw type!
public class Ticket implements Comparable
声明这样的内容会更合适:
// improved declaration! uses parameterized Comparable<T>
public class Ticket implements Comparable<Ticket>
现在我们可以写我们的compareTo(Ticket)
(不再compareTo(Object)
)。有很多方法可以重写它,但这里有一种相当简单的方法:
@Override public int compareTo(Ticket t) {
int v;
v = this.boeking.compareTo(t.boeking);
if (v != 0) return v;
v = compareInt(this.rijNr, t.rijNr);
if (v != 0) return v;
v = compareInt(this.stoelNr, t.stoelNr);
if (v != 0) return v;
v = compareInt(this.ticketType, t.ticketType);
if (v != 0) return v;
return 0;
}
private static int compareInt(int i1, int i2) {
if (i1 < i2) {
return -1;
} else if (i1 > i2) {
return +1;
} else {
return 0;
}
}
现在我们还可以定义equals(Object)
按照compareTo(Ticket)
而不是相反:
@Override public boolean equals(Object o) {
return (o instanceof Ticket) && (this.compareTo((Ticket) o) == 0);
}
注意结构compareTo
: 有多个return
陈述,但事实上,逻辑流程是相当可读的。另请注意如何priority排序标准是明确的,并且如果您有不同的优先级,则可以轻松重新排序。
相关问题
- 什么是原始类型以及为什么我们不应该使用它? https://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it
- 如何先按 x 然后按 y 对数组或 ArrayList ASC 进行排序? https://stackoverflow.com/questions/2741846/how-to-sort-an-array-or-arraylistpoint-asc-first-by-x-and-then-by-y
- 一个函数应该只有一个 return 语句吗? https://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement