Collections.sort排序异常:日期排序结果不符的原因与解决
日期排序异常排查与修复
我最近在尝试对Model列表按更新日期从新到旧排序时,遇到了一个奇怪的异常情况,这里分享我的排查过程和解决方案:
问题场景
我使用Collections.sort结合自定义Comparator对Model对象排序,代码如下:
Collections.sort(models, new Comparator<Model>() { @Override public int compare(Model item1, Model item2) { int s1 = (int) item1.getUpdateAt(); int s2 = (int) item2.getUpdateAt(); return (s2 - s1); } });
排序后得到的结果却不符合预期:
model: tyuiop time: 1484473575000
model: 0 time: 1516887006000
model: 1 time: 1516886848000
model: 2 time: 1516886840000
model: 3 time: 1516886833000
model: 4 time: 1516886825000
model: 5 time: 1516886818000
model: vhvyvtct time: 1516886592000
可以看到,从model 0到vhvyvtct的排序是正常的,但model tyuiop的位置明显错误,本该排在最后却出现在了最前面。
问题根源
经过排查,发现是long转int的类型溢出问题:
- Model的
getUpdateAt()返回的是long类型的毫秒级时间戳,而int类型的最大值仅为2147483647(对应约2038年的时间戳)。 - tyuiop的时间戳
1484473575000远大于int的最大值,强制转换为int后会变成负数,导致在s2 - s1的比较逻辑中,负数与正数的运算结果异常,最终导致排序位置错误。
解决方案
将时间戳的存储类型改为long,并使用Long.compare()方法进行比较(该方法会安全处理long值的比较,避免溢出问题),修正后的代码如下:
Collections.sort(models, new Comparator<Model>() { @Override public int compare(Model item1, Model item2) { long s1 = item1.getUpdateAt(); long s2 = item2.getUpdateAt(); return Long.compare(s2, s1); } });
修改后排序功能恢复正常,所有Model都能按更新日期从新到旧正确排序。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

