Java 7:java.lang.IllegalArgumentException:比较方法违反了其一般合同

时间:2014-01-09 20:11:56

标签: java java-7

我正在将项目升级到java 7.我遇到了Collections.sort()的Illegal Argument异常。我知道异常的原因是java 7中的新Timsort(尽管之前在此问题上提出了所有问题,但我确实抛出了)。现在我需要修改比较逻辑来克服异常。这是我的比较方法

if (o1.isLookup() && !o2.isLookup()) {
    return -1;
}
if (!o1.isLookup() && o2.isLookup()) {
    return 1;
}

if (o1.dependsOn(o2)) {
    return 1;
}
if (o2.dependsOn(o1)) {
    return -1;
}
return 0;
  1. 我尝试重写equals()方法,使用与compare相同的逻辑,认为如果equals和compare返回相同的结果它应该解决问题;但它没有按预期工作。

  2. 当我将比较方法分成两个独立的比较器时,如下所示,然后排序(使用两个比较器)不会抛出任何异常。可能的原因是什么?

  3. 以下代码:

    protected Comparator<EntityWrapper> getComparator2() {      
        return new Comparator<EntityWrapper>() {
            public int compare(EntityWrapper o1, EntityWrapper o2) {
                if (o1.dependsOn(o2.entityClass)) {
                    // This depends on otherWrapper
                    return 1;
                }
                if (o2.dependsOn(o1.entityClass)) {
                    // OtherWrapper depends on this
                    return -1;
                }
                return 0;
            }
        };
    }
    
    protected Comparator<EntityWrapper> getComparator1() {
        return new Comparator<EntityWrapper>() {
    public int compare(EntityWrapper o1, EntityWrapper o2) {
            if (o1.isLookup() && !o2.isLookup()) {
                return -1;
            }
            if (!o1.isLookup() && o2.isLookup()) {
                return 1;
            }
            return 0;
        };
    }
    

2 个答案:

答案 0 :(得分:2)

它也与JDK的版本有关。 JDK 7中的实现方法已更改,您违反了compareTo方法协定的3条规则之一。

看看这个:

描述:java.util.Arrays.sort和(间接)java.util.Collections.sort使用的排序算法已被替换。如果新的排序实现检测到违反Comparable合同的Comparable,则可能引发IllegalArgumentException。先前的实现默默地忽略了这种情况。如果需要以前的行为,则可以使用新的系统属性java.util.Arrays.useLegacyMergeSort还原以前的mergesort行为。

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

答案 1 :(得分:0)

您是不是错过了“.entityClass”,例如:

if (o1.isLookup() && !o2.isLookup()) {
    return -1;
}
if (!o1.isLookup() && o2.isLookup()) {
    return 1;
}

if (o1.dependsOn(o2.entityClass)) {
    return 1;
}
if (o2.dependsOn(o1.entityClass)) {
    return -1;
}
return 0;