[英]Why did I get this exception java.lang.IllegalArgumentException: Comparison method violates its general contract
I have this code.我有这个代码。 The getCreatedAt is a long representing the timestamp of the record.
getCreatedAt 是一个 long,表示记录的时间戳。
Collections.sort(records, new Comparator<Record>() {
@Override
public int compare(Record record1, Record record2) {
return (int) (record2.getCreatedAt() - record1.getCreatedAt());
}
});
When I run It with enough data (roughly 200 items in the list).当我用足够的数据运行它时(列表中大约有 200 个项目)。 I start to hit this exception
我开始遇到这个异常
java.lang.IllegalArgumentException: Comparison method violates its general contract!
java.lang.IllegalArgumentException:比较方法违反了它的一般约定!
Of course, I realized when I wrote this code that it could, in theory, have the integer overflow but feel it was unlikely since the timestamps would be days or weeks apart not decades.当然,当我编写这段代码时,我意识到理论上它可能会出现整数溢出,但我觉得不太可能,因为时间戳相隔几天或几周而不是几十年。
I have now fixed this by always returning 1, -1 or 0 but I am curious why this exception even happened in the first place.我现在通过总是返回 1、-1 或 0 来解决这个问题,但我很好奇为什么这个异常首先发生。
I assume the timestamps are long
s, because otherwise you wouldn't need the (int)
cast.我假设时间戳是
long
s,因为否则你不需要(int)
。
In that case, it's because of overflow.在这种情况下,这是因为溢出。
int
can hold values from -2147483648 up to 2147483647. If the subtraction result is bigger or smaller than that, then converting the result to an int
causes it to wrap around. int
可以保存从 -2147483648 到 2147483647 的值。如果减法结果大于或小于该值,则将结果转换为int
会导致它回绕。
For example, if record2.getCreatedAt()
is 2147483648, and record1.getCreatedAt()
is 0, then your function returns -2147483648 which indicates that record1 is greater (obviously wrong!).例如,如果
record2.getCreatedAt()
是 2147483648,而record1.getCreatedAt()
是 0,那么你的函数返回 -2147483648,这表明 record1 更大(显然是错误的!)。
Now by itself that's okay, it means you'll get things in the wrong order but it shouldn't crash, right?现在这本身没问题,这意味着你会以错误的顺序得到东西,但它不应该崩溃,对吧? Actually, it can cause a crash.
实际上,它可能会导致崩溃。
Let's call the one with 2147483648 record A, and the one with 0 record C. If there was another record B in the middle with a timestamp of say 1000000000, then your function says that C comes after A, A comes after B and B comes after C. It's a loop!让我们调用记录 A 为 2147483648 的记录 A 和记录 C 为 0 的记录。如果中间还有另一条记录 B 的时间戳为 1000000000,那么您的函数表示 C 在 A 之后,A 在 B 之后,B 在在 C 之后。这是一个循环! There's no way to sort these!
没有办法对这些进行排序!
Some sorting algorithms will return a not-properly-sorted list anyway, but the one that Java uses gets totally confused and throws an exception.一些排序算法无论如何都会返回一个排序不正确的列表,但 Java 使用的排序算法完全混淆并抛出异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.