代码这样的,其中startTime是时间戳
listUsed.sort(new Comparator<IdBean>() {
@Override
public int compare(IdBean o1, IdBean o2) {
int startTime2 = (int) o2.getStartTime();
int startTime1 = (int) o1.getStartTime();
return startTime2 - startTime1;
}
});
这个异常信息 IllegalArgumentException: Comparison method violates its general contract
表示你的比较器(Comparator)违反了其一般约定。在 Java 中,比较器必须是连贯的,并且要保持一致性,即它们必须符合下列条件:
- 自反性(Reflexivity):对于任何非空引用值
x
,x.compareTo(x)
应该返回零。 - 对称性(Symmetry):对于任何非空引用值
x
和y
,sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
。(这里的sgn
函数是一个数学符号函数,返回给定数字的正负号) - 传递性(Transitivity):对于任何非空引用值
x
,y
,z
,如果x.compareTo(y) > 0
并且y.compareTo(z) > 0
,那么x.compareTo(z) > 0
。
看起来问题出在 compare
方法中整型溢出的处理上。当你将 long
类型的时间戳转换为 int
时,如果时间戳值超过 int
能表示的最大值(即 Integer.MAX_VALUE 或者说 2^31 - 1),就会发生整型溢出,导致比较结果不准确。
而且,直接用 “减法” 来实现 compareTo
可能会导致溢出问题。当两个很大的 int
相减时可能会得到负数,而这个负数可能并不代表逻辑上的“小于”。同样地,对于很小的 int
相减也有类似问题。
改进的方法是,首先不要强制将 long
转换为 int
,其次使用安全的比较方法。可以像这样修改你的代码:
listUsed.sort(new Comparator<IdBean>() {
@Override
public int compare(IdBean o1, IdBean o2) {
long startTime1 = o1.getStartTime();
long startTime2 = o2.getStartTime();
return Long.compare(startTime2, startTime1); // 使用Long的比较
}
});
这里使用了 Long.compare(long x, long y)
方法,它避免了整型溢出的问题,并且正确地实现了比较逻辑。如果你的 getStartTime()
返回的是 long
类型,那么就不会有溢出的风险,而且 Long.compare
会按照预期进行比较。