Exception in thread “main“ java.lang.IllegalArgumentException:解决方案_exception in thread "main" java.lang.illegalargume-程序员宅基地

技术标签: Java  java  后端  异常记录及解决方法  开发语言  

昨天遇到一个很奇怪的异常,异常信息如下:

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
	at java.util.TimSort.mergeHi(TimSort.java:899)
	at java.util.TimSort.mergeAt(TimSort.java:516)
	at java.util.TimSort.mergeCollapse(TimSort.java:441)
	at java.util.TimSort.sort(TimSort.java:245)
	at java.util.Arrays.sort(Arrays.java:1512)
	at java.util.ArrayList.sort(ArrayList.java:1462)
	at com.example.testaspect.demo.TestC2.sortDateAndTimestamps(TestC2.java:33)
	at com.example.testaspect.demo.TestC2.main(TestC2.java:50)

报错的代码如下:

	list.sort((o1, o2) -> {
    
		if (o1 != null && o2 != null) {
    
			return o1.compareTo(o2);
		}
		return 0;
	});

看着语法好像也没什么问题啊,感觉很奇怪。而且在本地复现也没有复现,查看源码也是云里雾里的,说原因是判断一个len2==0了报错了,但是中间的处理逻辑十分复杂难懂,就在网上找答案。
很多解答说可以配置Java环境

 System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); 

也就是使用JDK1.6之前排序算法,但是总也觉得这不是一个很妥善的处理方式。

网上一篇解决这个问题的博文
Sort algorithm changes for Java 7 throws IllegalArgumentException
说这个问题是Java1.7使用了新的排序TimSort的问题,但是这个复现的是使用了Date和Timestamp,好像也和我遇到的不太一样,我用String的,也遇到了这样的问题。
后来,将null加入到了List中,居然真的复现了。

总结一下这个复现的特点:

  1. String类型的List需要存入null才会出现这个异常
  2. 数据条数太少的时候很难复现
  3. 异常并不是每次都会复现,需要多次运行才可能复现

复现的代码如下:

 List<String> list = new ArrayList<>();
 for (int i = 0; i < 31; i++) {
    
  	list.add("i=" + i);
  }
 list.add(null);
 for (int i = 0; i < 200000; i++) {
    
 	System.out.println(i);
  	Collections.shuffle(list);
	list.sort((o1, o2) -> {
    
		if (o1 != null && o2 != null) {
    
				return o1.compareTo(o2);
			}
		return 0;
		});
	System.out.println(list);
 }

经过多次运行,发现31条数据以上才更容易复现,也不是很明白为什么。那么怎么解决呢?
经过验证发现,以下方式修改,就不会再有这个异常了。

 list.sort((o1, o2) -> {
    
	if (o1 != null && o2 != null) {
    
		return o1.compareTo(o2);
	}
	if (o1 != null) {
    
		return 1;
	}
	if (o2 != null) {
    
		return -1;
	}
	return 0;
});

也就是增加了对“o1为空,o2不为空”、“o2为空,o1不为空”这两种情况的处理。也就是为了满足以下特性,根据具体场景进行修改

1) 自反性:x,y 的比较结果和 y,x 的比较结果相反。
2) 传递性:x>y,y>z,则 x>z。
3) 对称性:x=y,则 x,z 比较结果和 y,z 比较结果相同。

毕竟如果某一个为空,其他不为空默认认为它们是相等的也确实不合理。

总结,在JDK1.7之后,排序算法进行了修改,对排序规则的要求更高了,所以会报这个 异常。

解决方案

  1. 使用JDK1.6之前的方式:
    1. 在代码中的运行类添加环境配置代码:
     System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); 
    
    1. 在运行参数添加以下参数:
    -Djava.util.Arrays.useLegacyMergeSort=true
    
  2. 在编写代码时,根据具体比较,对不同的情况下本身不相等的情况下,不要不要把它们定义为相同,一定要进行区分,如String类就需要用
    list.sort((o1, o2) -> {
          
    		//都不为null
    		if (o1 != null && o2 != null) {
          
    			return o1.compareTo(o2);
    		}
    		//o1不为null,o2为null
    		if (o1 != null) {
          
    			return 1;
    		}
    		//o1为null,o2不为null
    		if (o2 != null) {
          
    			return -1;
    		}
    		//都为null
    		return 0;
    	}
    );
    
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/q1406689423/article/details/123002278

智能推荐

java毕业设计超市管理系统Mybatis+系统+数据库+调试部署_mybatis超市管理系统-程序员宅基地

文章浏览阅读127次。java毕业设计超市管理系统Mybatis+系统+数据库+调试部署。前端技术:Layui、HTML、CSS、JS、JQuery等技术。springboot基于springboot食品销售网站。springboot足球青训俱乐部管理后台系统。springboot研究生实验室综合管理系统。springboot基于OO模式的短租平台。springboot酒店物联网平台系统。_mybatis超市管理系统

排序算法1 -- 拓扑排序_拓扑排序核心算法-程序员宅基地

文章浏览阅读106次。基本的拓扑排序算法。_拓扑排序核心算法

EasyCwmp 安装-程序员宅基地

文章浏览阅读2k次。EasyCwmp 安装源代码下载地址为:http://easycwmp.org/download/easycwmp-1.8.6.tar.gz一般参考官网发布版本中README文件就可以成功安装,但是部分同学可能会遇到各种问题,本文按照官方提供的安装方法一步一步安装验证,其中遇到一些依赖库安装问题,已整理到本文安装步骤中。1. OpenWRT Linux 上安装 EasyCwmpEasyCwmp 部分EasyCwmp主要是在OpenWRT Linux平台上开发和测试的。下载:下载 easycwm_easycwmp 安装

方方-前端体系课程(二)_npm i sm2-程序员宅基地

文章浏览阅读1.6k次。文章目录10.【HTML全解】HTML标签10.1 视频: 英语小课堂![在这里插入图片描述](https://img-blog.csdnimg.cn/20191127001925570.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Fx..._npm i sm2

js数组的forEach方法能不能修改数组的值-程序员宅基地

文章浏览阅读3.4k次,点赞4次,收藏6次。如果要使用数组的forEach()方法对其改值时,需要直接通过arr[i]这种方式来更改。请看下面代码: // 数组改值 let arr = [1,3,5,7,9]; arr.forEach(function(item){ item..._foreach循环修改数组的值 js

Java基础知识面试题(二)(英语答案)-程序员宅基地

文章浏览阅读285次。汇总Java基础知识英语面试题

随便推点

uniapp 微信小程序实现走势图生成图片分享_如何做一个走势的小程序-程序员宅基地

文章浏览阅读1.4k次。项目场景:提示:当前页面分享时 把走势图生成一张图片 并且生成图文分享分享出去:效果图:走势图部分:提示:这部分是走势图部分的代码html:<view class="qiun-charts" > <canvas canvas-id="qykccanvasMixid" id="qykccanvasMixid" class="charts" @error="error" @touchstart="touchMi..._如何做一个走势的小程序

微信小程序界面设计——自定义一个好看的头图_微信小程序自定义头部图片-程序员宅基地

文章浏览阅读1.3k次。先看效果图源码<view style="overflow: hidden;"> <image src='http://static.iswenzi.com/image/headImg.jpg' mode='widthFix' style='width:100%; display: block; filter: blur(2rpx); transform: scale(1.2);'></image></view><view clas_微信小程序自定义头部图片

普林斯顿大学计算机科学排名,普林斯顿大学研究生计算机系统专业排名-程序员宅基地

文章浏览阅读170次。原标题:普林斯顿大学研究生计算机系统专业排名 普林斯顿地处纽约和费城之间,是一座别具特色的乡村都市,小城位于新泽西州西南的特拉华平原,面积约为7平方公里,东濒卡内基湖,西临特拉华河。普林斯顿的景色幽雅,四周绿树成荫、绿草丛丛,清澈的河水环绕着小城静静流淌;普林斯顿人口约为3万,绝大部分市民生活富裕;小城交通方便,距离纽约和费城只需大概1小时车程,加上小城恬静而又安详的生活,浓浓的文化氛围笼罩下的贵..._普林斯顿大学计算机科学

Linux中oracle——解决backspace和上下键使用出现乱码-程序员宅基地

文章浏览阅读88次。Vi编辑器修改文件.bash_profile可解决backspace出现乱码问题   使用SecureCRT或是pietty_ch连接到一台安装有Oracle DB 10g的RHEL4.2的机器,linux使用的shell是..._linux oracle里面上下键为乱码

推荐15个清爽简约风格的 HTML5 网站作品_清爽到极致的网站-程序员宅基地

文章浏览阅读6.2k次。本期的 HTML5 网站大观与大家分享15个精美的 HTML5 清爽简约风格网站。HTML5 是现在Web开发领域的热点,越来越多的开发人员开始使用 HTML5 来开发交互性强、效果出众的Web应用和..._清爽到极致的网站

IO流相关知识(File,字节流,字符流,特殊操作流(标准输入流,标准输出流,对象序列化与反序列化,properties与IO流结合-程序员宅基地

文章浏览阅读853次,点赞23次,收藏26次。面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。

推荐文章

热门文章

相关标签