Long类型比较,IllegalArgumentException: Comparison method violates its general contract

文章讨论了Java中Comparator接口在处理时间戳比较时遇到的IllegalArgumentException,原因在于整型溢出。提出改进方法,建议直接使用Long.compare避免溢出,确保比较逻辑的正确性。
摘要由CSDN通过智能技术生成

代码这样的,其中startTime是时间戳

listUsed.sort(new Comparator<IdBean>() {
            @Override
            public int compare(IdBean o1, IdBean o2) {
                int startTime2 = (int) o2.getStartTime();
                int startTime1 = (int) o1.getStartTime();
                return startTime2 - startTime1;
            }
        });

这个异常信息 IllegalArgumentException: Comparison method violates its general contract 表示你的比较器(Comparator)违反了其一般约定。在 Java 中,比较器必须是连贯的,并且要保持一致性,即它们必须符合下列条件:

  1. 自反性(Reflexivity):对于任何非空引用值 x, x.compareTo(x) 应该返回零。
  2. 对称性(Symmetry):对于任何非空引用值 xy, sgn(x.compareTo(y)) == -sgn(y.compareTo(x))。(这里的 sgn 函数是一个数学符号函数,返回给定数字的正负号)
  3. 传递性(Transitivity):对于任何非空引用值 x, y, z,如果 x.compareTo(y) > 0 并且 y.compareTo(z) > 0,那么 x.compareTo(z) > 0

看起来问题出在 compare 方法中整型溢出的处理上。当你将 long 类型的时间戳转换为 int 时,如果时间戳值超过 int 能表示的最大值(即 Integer.MAX_VALUE 或者说 2^31 - 1),就会发生整型溢出,导致比较结果不准确。

而且,直接用 “减法” 来实现 compareTo 可能会导致溢出问题。当两个很大的 int 相减时可能会得到负数,而这个负数可能并不代表逻辑上的“小于”。同样地,对于很小的 int 相减也有类似问题。

改进的方法是,首先不要强制将 long 转换为 int,其次使用安全的比较方法。可以像这样修改你的代码:

listUsed.sort(new Comparator<IdBean>() {
    @Override
    public int compare(IdBean o1, IdBean o2) {
        long startTime1 = o1.getStartTime();
        long startTime2 = o2.getStartTime();
        return Long.compare(startTime2, startTime1); // 使用Long的比较
    }
});

这里使用了 Long.compare(long x, long y) 方法,它避免了整型溢出的问题,并且正确地实现了比较逻辑。如果你的 getStartTime() 返回的是 long 类型,那么就不会有溢出的风险,而且 Long.compare 会按照预期进行比较。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值