摘要:最近一直在做底层方面的研究,所以这段时间就没写相关的东西,但恰巧今天同事问我一个问题,在帮他解决完这个问题之后,我发现,这个问题对新手来说还是非常容易犯的,所以在这里记录下。首先看下面这段代码这段代码的功能就是对进行排序,内元素类型是。
最近一直在做底层方面的研究,所以这段时间就没写java相关的东西,但恰巧今天同事问我一个问题,在帮他解决完这个问题之后,我发现,这个问题对java新手来说还是非常容易犯的,所以在这里记录下。
首先看下面这段代码:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; public class Test { public static void main(String[] args) { Listl = new ArrayList<>(); for (int i = 0; i < 100000; i++) { l.add(ThreadLocalRandom.current().nextLong()); } l.sort((o1, o2) -> (int) (o1 - o2)); // l.sort(Long::compare); } }
这段代码的功能就是对list进行排序,list内元素类型是long。
一眼看上去好像没啥大问题,执行看下:
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.base/java.util.TimSort.mergeLo(TimSort.java:781) at java.base/java.util.TimSort.mergeAt(TimSort.java:518) at java.base/java.util.TimSort.mergeCollapse(TimSort.java:448) at java.base/java.util.TimSort.sort(TimSort.java:245) at java.base/java.util.Arrays.sort(Arrays.java:1516) at java.base/java.util.ArrayList.sort(ArrayList.java:1749) at io.ytcode.game.test/test.Test.main(Test.java:14)
额,报错了(可能需要多执行几次才会报错,但并不影响本文内容),为什么呢?
这段代码大部分逻辑用的都是官方的api,所以这些地方肯定是没问题的,需要我们自己写逻辑的唯一的地方就是list.sort方法传递的参数:Comparator。
看下我们怎么写的,我们返回了 (int) (o1 - o2),看出问题了吗?
o1 - o2的结果还是long啊,如果这个值大于int范围,在我们把它转成int后,结果就溢出处理了,这时,该表达式返回的结果和我们预期的结果就不相同了。
我估计很多人都踩过这坑吧。
那正确的解决方式是什么呢?
把上面程序中的sort行注释掉,用它下面Long::compare的sort行,再试试是不是就可以了。
看下Long::compare的对应实现:
// java.lang.Long public static int compare(long x, long y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); }
这才是long的compare的标准方式!
还是那句话,官方库带有的方法就用官方的,这能让你少踩很多坑。
完。
更多原创文章,请关注我微信公众号:
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/75821.html
摘要:对于程序员来说,更意味着代码的组织,工作成员之间的协作方式。我常犯的一个错误是直接在或分支上直接,而团队是不允许这样做的。 先介绍下背景,博主由运营转行前端,入职一个月,完成了一个相对较大的模块。由于基础相对薄弱,犯下了不少错误,故想记录下来警醒自己和分享各位。 前端技术栈是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:对于程序员来说,更意味着代码的组织,工作成员之间的协作方式。我常犯的一个错误是直接在或分支上直接,而团队是不允许这样做的。 先介绍下背景,博主由运营转行前端,入职一个月,完成了一个相对较大的模块。由于基础相对薄弱,犯下了不少错误,故想记录下来警醒自己和分享各位。 前端技术栈是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:对于程序员来说,更意味着代码的组织,工作成员之间的协作方式。我常犯的一个错误是直接在或分支上直接,而团队是不允许这样做的。 先介绍下背景,博主由运营转行前端,入职一个月,完成了一个相对较大的模块。由于基础相对薄弱,犯下了不少错误,故想记录下来警醒自己和分享各位。 前端技术栈是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:原文出自本文总结了程序员常犯的个错误。可以看看为什么在中被设计成不可变父类和子类的构造函数以上这段代码出现编译错误,因为默认的父类构造函数未定义。如果程序员定义构造函数,编译器将不插入默认的无参数构造函数。 原文出自:http://www.programcreek.com/2014/05/top-10-mistakes-java-developers-make/ 本文总结了J...
阅读 2159·2021-11-19 09:55
阅读 2593·2021-11-11 16:55
阅读 3122·2021-09-28 09:36
阅读 1873·2021-09-22 16:05
阅读 3209·2019-08-30 15:53
阅读 1774·2019-08-30 15:44
阅读 2868·2019-08-29 13:10
阅读 1309·2019-08-29 12:30