当前位置: 首页 > 知识库问答 >
问题:

java.lang.IllegalArgumentException:比较方法违反了它的一般约定[重复]

堵昊焱
2023-03-14

嗨,下面是我的比较器的比较方法。我不知道哪里出了问题。我查了关于堆栈溢出的其他类似标题的问题和答案,但不确定我的方法有什么问题,但我不断得到java.lang.IllegalArgument异常:比较方法违反了它的一般合同!

任何帮助将不胜感激

public int compare(Node o1, Node o2)
{
    HashMap<Integer,Integer> childMap = orderMap.get(parentID);
    if(childMap != null && childMap.containsKey(o1.getID()) && 
                           childMap.containsKey(o2.getID()))
    {
        int order1 = childMap.get(o1.getID());
        int order2 = childMap.get(o2.getID());

        if(order1<order2) 
            return -1;
        else if(order1>order2) 
            return 1;
        else 
            return 0;
    }
    else
        return 0;
}

添加我得到的异常

java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:747)
at java.util.TimSort.mergeAt(TimSort.java:483)
at java.util.TimSort.mergeCollapse(TimSort.java:410)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)

共有2个答案

徐翔
2023-03-14

我认为问题出在您的默认情况下。考虑一组节点 A、B 和 C,其中 ID 为“a”、“b”“c”。进一步考虑包含相对排序信息的 childMap 具有以下内容:

{ 'a' => 1, 'c' => 3 }

现在,如果对A和B运行compare方法,则返回0,表示A和B是等价的。此外,如果比较B和C,仍然返回0。但是,如果比较A和C,则返回-1,表示A更小。这违反了Comparator约定的传递性属性:

实现者还必须确保关系是可传递的:((compare(x, y)

最后,实现者必须确保< code>compare(x,y)==0意味着< code>sgn(compare(x,z))==sgn(compare(y,z)) for all z

您不能将“未分配顺序的项目”视为具有“中间模糊位置”的值,因为排序算法不知道将它们放在哪里。如果您想继续使用这种方法,那么在地图中不存在值的情况下,您需要分配一个固定值作为排序号;像0MIN_INT这样的选择是合理的(但是任何选择都需要记录在Javadoc中用于比较!)。

邓丰
2023-03-14

您的< code>compare()方法是不可传递的。如果< code>A == B且< code>B == C,则< code>A必须等于< code>C。

现在考虑这种情况:

对于AB ,假设

  • childMap.contains键(A.getID)返回true
  • childMap.contains密钥(B.getID)返回false
  • childMap.contains键(C.getID)返回true

另外,考虑A.getId() ! = B.getId()的顺序。

所以,

    < li> A和< code>B将返回< code>0,作为外部< code>if条件将为< code>false =

但是,AC,可以根据您在if块中的测试返回-11。因此,A!=C。这违反了传递性原则。

我认为,您应该在else块中添加一些条件,该条件执行类似于您在if块中执行的检查。

 类似资料:
  • 问题内容: 您好,以下是我的比较器的比较方法。我不确定是什么问题。我在堆栈溢出时查找了其他类似标题的问题和答案,但不确定我的方法有什么问题,但我一直在获取java.lang.IllegalArgumentException:比较方法违反了它的一般约定! 任何帮助将不胜感激 添加我得到的异常 问题答案: 您的方法 不是可 传递的 。如果和,则必须等于。 现在考虑这种情况: 对于,和,假设方法返回以下

  • 使用自定义比较器执行< code > Collection.sort using >时,我得到一个< code > Java . lang . illegalargumentexception:Comparison方法违反了它的一般约定 我理解这是一个问题,因为该方法是不可传递的。在我的比较器中,调用了多个方法,我确定了违反此规则的代码段。然而,我无法修复它,也看不到它的问题。

  • 一切似乎都运行良好(几天),但我只遇到了一次问题,并且很难重现该问题。 “比较方法违反了其总合同!”被抛出,完全让我措手不及。我有以下几点: 我的染色体类别: 我有一个ArrayList,我使用了两个Collections。排序(MyList)和集合。排序(MyList,Collections.reverseOrder())。到目前为止,他们仍在正常工作。我在100次跑步中只遇到过一次错误。这个实

  • 我试图重现这个异常(java.lang.IllegalArgumentExc的:比较方法违反了它的一般合同!)因为我需要调试一段代码,但下面的代码从不抛出它, 此外,当我检查JDK代码时,似乎只有当要排序的集合的大小大于32时,Collections.sort方法才会抛出这个异常。。应该在代码块中进行什么样的更改,以便Collections.sort抛出这个异常。

  • 我所拥有的 我有此代码,用于根据名称,日期或大小对文件进行排序。 但我得到了这个错误, 我的一些用户得到了这个错误,我在崩溃报告中看到了它。但我自己无法以任何方式重现这个错误。 任何人都可以帮助我找到问题。我似乎真的花了很多时间,但找不到任何东西。请帮我吗? 提前谢谢。

  • 我想通过dateLastContact比较两个“收件人”,如果相同,就通过地址进行比较。这是我的代码: 而且我总是有这个错误: 我尝试了很多方法,但是现在,我不知道该怎么办。你能帮我吗? 收件人类别: