Java “;比较法违反其总合同”;
我在谷歌上搜索了一些相同的问题,我知道原因。但是这次坠机只发生过一次,所以我来这里问你什么可能导致坠机Java “;比较法违反其总合同”;,java,Java,我在谷歌上搜索了一些相同的问题,我知道原因。但是这次坠机只发生过一次,所以我来这里问你什么可能导致坠机 Collections.sort(downloadTasks, new Comparator<DownloadTask>() { @Override public int compare(DownloadTask lhs, DownloadTask rhs) { if (lhs == null || rhs == nu
Collections.sort(downloadTasks, new Comparator<DownloadTask>() {
@Override
public int compare(DownloadTask lhs, DownloadTask rhs) {
if (lhs == null || rhs == null) return 0;
return (int) (lhs.mTaskInfo.time - rhs.mTaskInfo.time);
}
});
这两种情况都有问题
if(lhs==null | | rhs==null)返回0代码>
如果您有[123,null,234]
,那么您可以将123
与null
进行比较,null
与234
进行比较,通过传递性,您应该得到123
等于234
。但这不是比较器返回的结果
这里的解决方案是不允许null
或将所有null
排序到底部(或顶部),即仅返回0
是两个都null
,否则返回1
或-1
(取决于null
是左还是右)
返回(int)(lhs.mTaskInfo.time-rhs.mTaskInfo.time)
考虑将Integer.MAX_值+1
与0
进行比较。两者之间的差异是Integer.MAX_值+1
。将该值转换为int
将换行为Integer.MIN\u值
。然后,相反的比较应给出-Integer.MIN_值
,但是
这里的解决方案是使用Long。比较(a,b)
比较方法的javadoc中详细记录了比较方法的“总合同”:
实施者必须确保所有x
和y
的sgn(比较(x,y))==-sgn(比较(y,x))
。(这意味着compare(x,y)
必须在且仅当compare(y,x)
引发异常时才会引发异常。)
实现者还必须确保关系是可传递的:((比较(x,y)>0)和&(比较(y,z)>0))
意味着比较(x,z)>0
最后,实现者必须确保compare(x,y)==0
意味着所有z的sgn(compare(x,z))==sgn(compare(y,z))
那么,你违反了这三条规则中的哪一条全部3个
违反第一条规则是因为time
是一个long
,所以(int)(lhs.mTaskInfo.time-rhs.mTaskInfo.time)
可以等于整数.MIN\u值。如果将这两个参数翻转到compare()
,结果仍然是Integer.MIN\u值
,因为int
值不能存储取反的值
第二条规则被违反,因为int
溢出。由于time
是long
,因此我假设它们包含标准的毫秒值,int
最多只能存储24天的值。假设输入是1月1日、1月15日、1月30日<代码>比较(1月1日,1月15日)
是+14天,而比较(1月15日,1月30日)
是+15天,但是比较(1月1日,1月30日)
应该是+29天,但它溢出的返回时间大约是-19天。哎呀
由于错误的空检查,违反了第三条规则。假设输入为空,1月1日,1月2日
<代码>比较(空,1月1日)是0,比较(空,1月2日)
也是0,但是比较(1月1日,1月2日)
是+1天
解决方案
int
溢出和MIN\u值
问题可以通过使用轻松解决
对于null
问题,您需要决定null应该首先排序还是最后排序。以下内容将首先对空值进行排序:
public int compare(DownloadTask lhs, DownloadTask rhs) {
if (lhs == null) {
if (rhs == null)
return 0;
return -1;
}
if (rhs == null)
return 1;
return Long.compare(lhs.mTaskInfo.time, rhs.mTaskInfo.time);
}
或单语句版本:
public int compare(DownloadTask lhs, DownloadTask rhs) {
return (lhs == null ? (rhs == null ? 0 : -1)
: (rhs == null ? 1 : Long.compare(lhs.mTaskInfo.time, rhs.mTaskInfo.time)));
}
什么撞车?你会得到什么错误,什么时候,用什么代码,发生了什么,你期望发生什么?看一看,因为标题上说错误是
比较方法违反了它的一般约定你能解释一下为什么演员阵容会导致崩溃吗@我同意你的看法。你能写下你的答案吗?在减法之前试着施法。答案很棒而且清晰。非常感谢。
public int compare(DownloadTask lhs, DownloadTask rhs) {
return (lhs == null ? (rhs == null ? 0 : -1)
: (rhs == null ? 1 : Long.compare(lhs.mTaskInfo.time, rhs.mTaskInfo.time)));
}