Java排序Comparator实现接口发生异常

Java排序Comparator实现接口发生异常

异常场景

在JDK8环境下,通过实现Comparator接口,对HashMap根据value降序排序

出异常的Comparator

    private static class ValueComparator implements Comparator<Map.Entry<String, Long>> {
        public int compare(Map.Entry<String, Long> m, Map.Entry<String, Long> n) {
            return n.getValue() > m.getValue() ? 1 : -1;
        }
    }

异常信息

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

异常原因

JDK7/JDK8的Collections.Sort方法实现中,如果两个值是相等的,那么compare方法需要返回0,否则 **可能** 会在排序时抛错,而JDK6是没有这个限制的。

不同版本JDK中Comparator约束差异

在 JDK7/JDK8(当前JDK8),Comparator 要满足自反性传递性对称性,不然 Arrays.sort,Collections.sort 会报 IllegalArgumentException 异常。(JDK7 Comparator,JDK8 Comparator)

说明:

1) 自反性:x,y 的比较结果和 y,x 的比较结果相反。

2) 传递性:x>y,y>z,则 x>z。

3) 对称性:x=y,则 x,z 比较结果和 y,z 比较结果相同。

Comparator在实现时需要遵照以下约束:


sgn(x):=1,0,1,if x < 0if x = 0if x > 0

根据约束Comparator实现做如下修改:

    private static class ValueComparator implements Comparator<Map.Entry<String, Long>> {
        public int compare(Map.Entry<String, Long> m, Map.Entry<String, Long> n) {
            long x = n.getValue().longValue();
            long y = m.getValue().longValue();
            return (x < y) ? -1 : ((x == y) ? 0 : 1);
            //可以直接使用compareTo方法 
            //return n.getValue().compareTo(m.getValue());
        }
    }

在JDK7/JDK8文档中对Comparator实现虽然说不严格要求遵循约束,比方说上述出异常的Comparator,在执行时不一定会报异常,但是为了程序稳定性,最好是遵循约束。至于JDK7之后的Comparator底层排序实现算法Timsort原理,可阅读以下几篇文章:

Timsort原理介绍

深入理解 timsort 算法

参考

图解JDK7的Comparison method violates its general contract异常

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值