首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java错误: java.lang.IllegalArgumentException:比较方法违反其常规约定

Java错误: java.lang.IllegalArgumentException:比较方法违反其常规约定
EN

Stack Overflow用户
提问于 2020-02-10 21:28:37
回答 2查看 56关注 0票数 1

我正在开发一个旧的应用程序,它最初是用Java6编写的,几年前升级到了Java7。

在这个应用程序中,我使用Collection.Sort通过实现Comparator接口,使用自定义的compare方法对列表进行排序。列表中的对象类型是具有3个属性companyNameScheduleexpirationdateCompanySchedule

列表可以包含多个具有相同companyName但具有唯一过期日期的对象。下面的比较函数在相同的companyName列表中以companyName和with的升序和到期日期的降序对列表进行排序。下面是方法的实现。

代码语言:javascript
复制
    public int compare(CompanySchedule c1, CompanySchedule c2) {
        int returnVal = 0;
        int value = c1.getCompany().getName().compareTo(c2.getCompany().getName());
        if (value == 0){
            if (c1.getUseExpirationDate() == null || c2.getUseExpirationDate() == null){
                returnVal = -1;
            }
            else{
                int chkdate = c1.getUseExpirationDate().compareTo(c2.getUseExpirationDate());
                if (chkdate == 0){
                    returnVal = 0;
                }
                else if (chkdate > 0){
                    returnVal = -1;
                }
                else if (chkdate < 0){
                    returnVal = 1;
                }
            }
        }
        else if (value < 0){
            returnVal = -1;
        }
        else if (value > 0){
            returnVal = 1;
        }


        return returnVal;
    }

我知道,当在上面的compare方法实现中不满足可传递属性时,将抛出错误java.lang.IllegalArgumentException: Comparison method violates its general contract

是否有人可以帮助确定此方法将在何处违反传递性。谢谢你的帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-10 21:36:26

我认为这里有一个问题:

代码语言:javascript
复制
if (c1.getUseExpirationDate() == null || c2.getUseExpirationDate() == null){
                returnVal = -1;
}

如果a.getUseExpirationDate() == null和b.getUseExpirationDate() == null,您将得到a

这破坏了一致性。这个方法可能有更多的问题,但我还没有全部检查过。

祝好运。

编辑

这段代码怎么样?

代码语言:javascript
复制
public int compare(CompanySchedule c1, CompanySchedule c2) {
        int returnVal = 0;
        int value = c1.getCompany().getName().compareTo(c2.getCompany().getName());
        if (value == 0) {
            if (c1.getUseExpirationDate() == null && c2.getUseExpirationDate() != null) {
                returnVal = -1;
            } else if (c1.getUseExpirationDate() != null && c2.getUseExpirationDate() == null) {
                returnVal = 1;
            } else if (c1.getUseExpirationDate() == null && c2.getUseExpirationDate() == null) {
                returnVal = 0;
            } else {
                int chkdate = c1.getUseExpirationDate().compareTo(c2.getUseExpirationDate());
                if (chkdate == 0) {
                    returnVal = 0;
                } else if (chkdate > 0) {
                    returnVal = -1;
                } else if (chkdate < 0) {
                    returnVal = 1;
                }
            }
        } else if (value < 0) {
            returnVal = -1;
        } else if (value > 0) {
            returnVal = 1;
        }


        return returnVal;
    }

为了可比性,我尽量不对其进行太多更改,但应该对其进行重构。基本上,它确定空值比其他值小。

票数 1
EN

Stack Overflow用户

发布于 2021-12-01 12:03:31

我知道我来晚了,一旦我找到了解决方案,我基本上忘记了我问过这个问题。因此,正如我所提到的,该应用程序是用Java6编写的,然后根据我对集合的内部实现的理解,升级到了Java 7

Sort方法将使用的算法从Merge sort更改为Tim Sort,Merge sort忽略compare方法实现的传递性属性,但是,Tim Sort要求compare方法实现是可传递的,否则将引发上述异常,因为我们有一个遗留应用程序,我们不想更改代码中的任何内容,因此我们在Sort实现中内部使用了jvm参数java.util.Arrays.useLegacyMergeSort=true Merge sort

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60151470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档