前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java新手非常容易犯的一个错误

Java新手非常容易犯的一个错误

作者头像
KINGYT
发布2019-08-06 14:49:36
8310
发布2019-08-06 14:49:36
举报

最近一直在做底层方面的研究,所以这段时间就没写java相关的东西,但恰巧今天同事问我一个问题,在帮他解决完这个问题之后,我发现,这个问题对java新手来说还是非常容易犯的,所以在这里记录下。

首先看下面这段代码:

代码语言:javascript
复制
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

public class Test {

  public static void main(String[] args) {
    List<Long> l = 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。

一眼看上去好像没啥大问题,执行看下:

代码语言:javascript
复制
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的对应实现:

代码语言:javascript
复制
// java.lang.Long
public static int compare(long x, long y) {
    return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

这才是long的compare的标准方式!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linux内核及JVM底层相关技术研究 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档