[List排序报错 - Comparison method violates its general contract!]

在JDK1.7之后,ArrayList的默认排序方式做了修改,使用TimeSort排序算法来排序

但是,此排序算法比老版本的算法多了如下几个限制条件,如果不注意,排序可能会抛异常

 1. 自反性,compare(x, y) = - compare(y, x)
 2. 传递性,如果compare(x, y) > 0, compare(y, z) > 0, 则必须保证compare(x, z) > 0
 3. 对称性, 如果compare(x, y) == 0, 则必须保证compare(x, z) == compare(y, z)

   如果不满足以上3个条件,TimeSort并不是一定会报错,在某些序列条件下才会报错,这与TimeSort的排序逻辑有关。同时只有在排序序列长度在32以上时才有可能抛异常,因为在排序序列长度小于32时,TimeSort会直接退化为二分排序

   JDK1.7之后的标准排序方式如下,以长整形为例,其它对象类似:(此处没考虑为Null的情况,如果有可能为null,代码逻辑要保证满足上述的三个条件)

@Override
public int compare(Long a, Long b) {
    return a == b ? 0 : (a > b ? 1 : -1);
}

 常见的几种错误排序方式(JDK1.7之前可以使用,1.7之后可能会异常)

1. 未判断相等的情况,及不满足自反性

@Override
public int compare(Long a, Long b) {
    return a > b ? 1 : -1;
}

 此处未判断相等的情况,如果 x==y, compare(x, y) = -1, compare(y, x) == -1, 即compare(x, y) == compare(y, x)

  附上一个会抛异常的序列:

    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
                    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,1,0,-2,0,0,0,0}

2. 不满足传递性

@Override
public int compare(Long a, Long b) {
    return (int)(a-b);
}

此写法存在溢出的可能,当有溢出发生时,可能会导致传递性不满足,从而会报错。如下可以看到 :

    x > y, y > z, 但是 x < z

附上一个会抛异常的序列:

    {1145134726, -682584886, 1895454242, 2004378087, -1855696367, 1813048944, -1506811635, -1271811878, 1612219267, 838774780, -1749593269, -1721719275, 1908610116, 1732597731, 958982535, -937016328, 122618972, 775687877, -466649843, 1212803556, 2141188937, -1192216148, 815915713, 2001074718, 590322195, 1498442902, 1985922385, 417233400, 1631605406, -1900707536, -1345360210, -1732308942, -287293378};

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值