我搜索了一些同样的问题而且我知道原因。但是只发生一次坠机,所以我来这里问你可能会导致什么事情崩溃。
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);
}
});
错误是:
java.lang.IllegalArgumentException:比较方法违反了其一般合同!在java.util.TimSort.mergeHi(TimSort.java:864) 在java.util.TimSort.mergeAt(TimSort.java:481) 在java.util.TimSort.mergeCollapse(TimSort.java:406) 在java.util.TimSort.sort(TimSort.java:210) 在java.util.TimSort.sort(TimSort.java:169) 在java.util.Arrays.sort(Arrays.java:2010) 在java.util.Collections.sort(Collections.java:1883)
如您所见,我通过time
成员比较两个对象。 time
是long
类型。
我认为崩溃可能来自:
如果lhs
和rhs
可以为空,我该怎么办?
在Android中,Long.compare()
需要API 19.您可以在API 19下执行此操作:
public static int compare(long lhs, long rhs) {
return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);
}
答案 0 :(得分:5)
这两种情况都有问题。
if (lhs == null || rhs == null) return 0;
如果你有[123, null, 234]
,那么你将123
等同于null
,将null
等同于234
,并通过及物性来获得123
{1}}等于234
。但这不是比较器返回的原因。
此处的解决方案是禁止null
或将所有nulls
排序到底部(或顶部),即只返回0
两者是null
,否则返回1
或-1
(取决于左侧或右侧null
)。
return(int)(lhs.mTaskInfo.time - rhs.mTaskInfo.time);
考虑将Integer.MAX_VALUE + 1
与0
进行比较。两者之间的差异是Integer.MAX_VALUE + 1
。将其转换为int
换行到Integer.MIN_VALUE
。然后,相反的比较应该为您提供- Integer.MIN_VALUE
,但that is Integer.MIN_VALUE
again due to overflow。
此处的解决方案是使用Long.compare(a,b)
。
答案 1 :(得分:2)
比较方法的“一般合同”在compare(T o1, T o2)
方法的javadoc中有详细记录:
实施者必须确保所有
sgn(compare(x, y)) == -sgn(compare(y, x))
和x
都y
。 (这意味着compare(x, y)
当且仅当compare(y, x)
抛出异常时才必须抛出异常。)实现者还必须确保关系具有传递性:
((compare(x, y)>0) && (compare(y, z)>0))
隐含compare(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)
可以等于Integer.MIN_VALUE
。如果您将两个参数翻转为compare()
,结果仍为Integer.MIN_VALUE
,因为int
值无法存储否定值。
违反了第二条规则,因为int
溢出。由于time
为long
,我会假设它们包含标准的毫秒值,而int
只能存储最多 24天的值。所以我们说输入是Jan 1, Jan 15, Jan 30
。 compare(Jan 1, Jan 15)
为+14天,compare(Jan 15, Jan 30)
为+15天,但compare(Jan 1, Jan 30)
应为+29天,但溢出的回报类似于-19天。糟糕!!!!
由于错误的空检查,违反了第三条规则。假设输入为null, Jan 1, Jan 2
。 compare(null, Jan 1)
为0,compare(null, Jan 2)
也是compare(Jan 1, Jan 2)
,但int
为+1天。
解决方案
使用Long.compare(long x, long y)
可以轻松修复MIN_VALUE
溢出和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)));
}
或单语句版本:
override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if indexPath.item >= allEvents.count - 1 {
// print("paginating for post")
paginationHelper.paginate(completion: { [unowned self] (events) in
self.allEvents.append(contentsOf: events)
DispatchQueue.main.async {
self.collectionView?.reloadData()
}
})
}else{
print("Not paginating")
}
}