当我在下面的比较器对我得到的对象进行排序时,比较方法违反了其在比较器中的一般合约问题。
final Set<Span> set = new TreeSet<Span>(new Comparator<Span>() {
public int compare(final Span firstSpan, final Span secSpan) {
BigInteger s1X0 = firstSpan.getCoordinates().getX0();
BigInteger s1X1 = firstSpan.getCoordinates().getX1();
BigInteger s2X0 = secSpan.getCoordinates().getX0();
BigInteger s2X1 = secSpan.getCoordinates().getX1();
BigInteger s1Y0 = firstSpan.getCoordinates().getY0();
final BigInteger s2Y0 = secSpan.getCoordinates().getY0();
if(s1X0.intValue() == s2X0.intValue() && s1X1.intValue() == s2X1.intValue() && s1Y0.intValue() == s2Y0.intValue()){
return 0;
}
if ((s1Y0.intValue() - s2Y0.intValue() <= 5) && (s1Y0.intValue() - s2Y0.intValue() >= -5)) {
return (s1X0.intValue()>s2X0.intValue()) ? 1 : -1;
} else {
if ((s1X0.intValue() >= s2X0.intValue() && s1X0.intValue() <= s2X1.intValue())
|| (s2X0.intValue() >= s1X0.intValue() && s2X0.intValue() <= s1X1.intValue())) {
return (s1Y0.intValue() > s2Y0.intValue()) ? 1 : -1;
} else {
return s1X0.intValue() > s2X0.intValue() ? 1 : -1;
}
}
}
});
Comparator
必须对它比较的对象施加总排序。特别是这意味着它必须是传递的,即如果a
小于b
,而b
小于c
,则a
必须小于c
。您的Comparator
没有该属性。
请考虑以下示例:
a.getX0() == 1 b.getX0() == 2 c.getX0() == 3
a.getX1() == 4 b.getX1() == 5 c.getX1() == 6
a.getY0() == 4 b.getY0() == 0 c.getY0() == -4
然后它认为a
小于b
(y0 的差值小于 5(,b
小于 c
(差值 y0 小于 5(,但a
不小于 c
(y0 的差值大于 5,所以取 y0 值(。
这三个对象应该按什么顺序排序?
此外,您的代码还有其他问题。如果将所有内容转换为 int
,可能会发生溢出(这也可能导致您提到的异常(。当数据存储为 BigInteger
时,您还应该使用 BigInteger
s 进行比较,例如使用方法 BigInteger.subtract
和 BigInteger.compare
。
通过使用BigInteger.intValue,你只是假设你的所有数字都适合简单的整数。
由于 BigInteger 是可比较的,因此您应该依赖 BigInteger.compare 而不是比较整数值。