Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Java新手非常容易犯的一个错误

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

作者头像
KINGYT
发布于 2019-08-06 06:49:36
发布于 2019-08-06 06:49:36
83700
代码可运行
举报
运行总次数:0
代码可运行

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

首先看下面这段代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
// 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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JDK错误用法—TimSort
Tim Peters在2002年设计了该算法并在Python中使用(TimSort 是Python中list.sort的默认实现),后被引入java。TimSort算法是一种归并排序和插入排序的混合排序算法,设计初衷是为了在真实世界中的各种数据中可以有较好的性能。基本工作过程是:
早安嵩骏
2020/08/11
8530
comparator 排序报错IllegalArgumentException
使用comparator 排序报错,十几条不出任何问题,正常排序,当超过100条数据时跑错java.lang.IllegalArgumentException
Antler
2019/01/06
1.2K0
JDK7的Comparison method violates its general contract异常
前一阵遇到了一个使用Collections.sort()时报异常的问题,跟小伙伴@zhuidawugui 一起排查了一下,发现问题的原因是JDK7的排序实现改为了TimSort,之后我们又进一步研究了一下这个神奇的算法。
用户6182664
2019/10/08
1.7K0
JDK7的Comparison method violates its general contract异常
Comparison method violates its general contract!
本文讲述了在JDK6和JDK7中关于Collections.sort()方法的一个不同之处,以及相关的异常处理。在JDK6中,当两个元素相等时,排序不会抛出异常,但在JDK7中会抛出异常。为了解决这个问题,可以使用return x > y ? 1 : -1;语句来修改比较逻辑。
高爽
2017/12/28
1.2K0
Comparison method violates its general contract!
Collections.sort()源码分析(基于JAVA8)
此类仅包含操作或返回集合的静态方法。 它包含多样的对集合进行操作的算法,“包装器”,返回由指定集合支持的新集合,以及其他一些细碎功能。
JavaEdge
2018/05/16
2.2K0
Spring Boot 2.6以上整合Swagger的问题:"this.condition" is null
前段时间看到群里有吐槽swagger整合问题,当时没仔细看,总以为是姿势不对。 这两天正好自己升级Spring Boot版本,然后突然出现了这样的一个错误: Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null
程序猿DD
2022/05/30
2.3K0
Spring Boot 2.6以上整合Swagger的问题:"this.condition" is null
Arrays.Sort()中的那些排序算法
Arrays.Sort方法所用的排序算法主要涉及以下三种:双轴快速排序(DualPivotQuicksort)、归并排序(MergeSort)、TimSort,也同时包含了一些非基于比较的排序算法:例如计数排序。其具体最终使用哪一种排序算法通常根据类型以及输入长度来动态抉择。
Rekent
2021/03/05
8600
Arrays.Sort()中的那些排序算法
源码阅读--Collections.sort
这是一个boolean值。说白了就是,如果用户指定归并排序那就归并排序,否则就是ComparableTimSort。归并排序比较常见,就不讲了。贴一下ComparableTimSort
提莫队长
2019/02/21
5310
Java 排序遇到的神坑,我替你踩了!
作者:nxlhero 来源:https://blog.51cto.com/nxlhero/2515850
Java技术栈
2020/11/23
1.3K0
读 Java Arrays 源码 笔记
Arrays.java是Java中用来操作数组的类。使用这个工具类可以减少平常很多的工作量。了解其实现,可以避免一些错误的用法。 它提供的操作包括: 排序 sort 查找 binarySearch() 比较 equals 填充 fill 转列表 asList() 哈希 Hash() 转字符串 toString() 这个类的代码量很多,Java1.7中有4000多行。因为每一种基本类型都做了兼容,所以整个类真正逻辑不多。下面简单介绍一下它各个功能的实现: 排序 这里的排序实现有两种 一种是为基本类型数组设计的
程序员互动联盟
2018/03/16
1.1K0
数组转换成list集合_字符串转数组js
为了实现把一个数组转换成一个ArrayList,很多Java程序员会使用如下的代码:
全栈程序员站长
2022/09/29
4.2K0
数组转换成list集合_字符串转数组js
面经手册 · 第10篇《扫盲java.util.Collections工具包,学习排序、二分、洗牌、旋转算法》
好的算法搭配上合适的数据结构,可以让代码功能大大的提升效率。当然,算法学习不只是刷题,还需要落地与应用,否则到了写代码的时候,还是会for循环+ifelse。
小傅哥
2020/09/16
3970
面经手册 · 第10篇《扫盲java.util.Collections工具包,学习排序、二分、洗牌、旋转算法》
Java基础(十八):java比较器、系统相关类、数学相关类
冬天vs不冷
2025/01/21
870
Java基础(十八):java比较器、系统相关类、数学相关类
Java源码系列(1):Comparable和Comparator的区别
在讲Comparable和Comparator区别之前,先补充一个知识点。 先看代码: Person类
陈琛
2020/06/12
4010
Java源码系列(1):Comparable和Comparator的区别
(31) 剖析Arrays / 计算机程序的思维逻辑
数组是存储多个同类型元素的基本数据结构,数组中的元素在内存连续存放,可以通过数组下标直接定位任意元素,相比我们在后续章节介绍的其他容器,效率非常高。 数组操作是计算机程序中的常见基本操作,Java中有一个类Arrays,包含一些对数组操作的静态方法,本节主要就来讨论这些方法,我们先来看怎么用,然后再来看它们的实现原理。学习Arrays的用法,我们就可以避免重新发明轮子,直接使用,学习它的实现原理,我们就可以在需要的时候,自己实现它不具备的功能。 用法 toString Arrays的toString方法可
swiftma
2018/01/31
1.4K0
java8 Stream sorted()的一次调用链记录
看到结果不淡定了,因此决定调试一下看看内部包装了哪种排序算法,这一调试不得了,发现stream的调用链有点奇怪:
xiaoxi666
2018/10/29
2.3K0
java中的compareto方法的详细介绍
1.返回参与比较的前后两个字符串的asc码的差值,如果两个字符串首字母不同,则该方法返回首字母的asc码的差值
全栈程序员站长
2022/09/07
1.6K0
Java8新特性
Lambda 是一个匿名函数,可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使 Java 的语言表达能力得到了提升。
程序员Leo
2023/08/08
3500
Java8新特性
浅谈 Java 中的 Lambda 表达式
Lambda 表达式是一种匿名函数,它可以作为参数传递给方法或存储在变量中。在 Java8 中,它和函数式接口一起,共同构建了函数式编程的框架。
浪漫主义狗
2023/09/04
3810
浅谈 Java 中的 Lambda 表达式
使用Java中Collections工具类和Comparator比较器使用
Collections工具类 介绍 Collections是单列集合的工具类,里面所有的方法都是静态方法,可以对集合进行一些操作。 常用方法(常用方法) 方法 说明 static void shuf
用户9006224
2022/12/21
4470
使用Java中Collections工具类和Comparator比较器使用
相关推荐
JDK错误用法—TimSort
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验