java.lang.IllegalArgumentException: Comparison method violates its general contract!

最近线上报了个异常,java.lang.IllegalArgumentException: Comparison method violates its general contract!;代码定位如下:

通过改为如下方式,可以解决问题:

或者

下面给出一个代码示例,可以模拟运行报错:

    public static void main(String[] args) {
		while(true) {
			Random random = new Random();
			List<Integer> list = new ArrayList<>();
			for(int i=0;i<32;i++) {
				list.add(random.nextInt(16));
			}
			System.out.println(list);
			list.sort((c1,c2)->{
				return c1>c2?-1:1;
			});
			System.out.println(list);
		}
	}

运行很快会报错:

通过报错信息,我们看到报错的是一个TimSort类,起始位置时Arrays.sort方法:

关于jdk1.8中Arrays.sort方法,其大致算法思想如下图:

其中TimSort算法是重点,TimSort算法是结合了插入排序和合并排序思想,基于现实数据通常是部分有序的状态,而优化出的更有效率的排序算法,它由Tim Peters于2002年实施并首次使用在Python编程语言中,java在jdk1.7版本开始引入TimSort算法,并兼容保留了jdk1.6版本的排序算法, 可以通过System.setProperty("java.util.Arrays.useLegacyMergeSort", "true") 来指定使用旧版本算法(报错的代码在此算法下是不会有问题的)。

TimSort是稳定的算法,对于比较器要满足如下约束:

1、f(x,y) == -f(y,x);

2、if f(x,y)>0 and f(y,z)>0 then f(x,z)>0;

3、if f(x,y)==0 and f(x,z)>0 then f(y,z)>0;

再看我们开始的代码,如果c1==c2,f(c1,c2)=1 and f(c2,c1)=1,就违反了第一个约束,所以我们一开始的代码在运行过程中才会报错。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值