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

Java集合排序:比较方法违反其一般契约

戚建白
2023-03-14

我知道它已经被询问和回答了数百万次,但我仍然无法弄清楚为什么我在排序期间收到了违规。这是我的代码

Collections.sort(sorted, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject m1, MyObject m2) {
        // Actual energy comparison :-
        // THE higher the energy, the earlier in the list
        float delta = m1.getTotalEnergy() - m2.getTotalEnergy();

        if (delta > 0) {
            return 1;
        } else if (delta < 0) {
            return -1;
        } else {
            return 0;
        }
    }
});

我收到了这个错误

java.lang.IllegalArgumentException: Comparison method violates its general contract!  
        at java.util.TimSort.mergeHi(TimSort.java:895)  
        at java.util.TimSort.mergeAt(TimSort.java:512)  
        at java.util.TimSort.mergeForceCollapse(TimSort.java:453)  
        at java.util.TimSort.sort(TimSort.java:250)  
        at java.util.Arrays.sort(Arrays.java:1512)  
        at java.util.ArrayList.sort(ArrayList.java:1454)  
        at java.util.Collections.sort(Collections.java:175)

有什么想法吗?

共有3个答案

卢知
2023-03-14

也许这会做出改变:

public int compare(Object m1, Object m2) {
    // Actual energy comparison :-
    // THE higher the energy, the earlier in the list
    float delta = ((MyObject)m1).getTotalEnergy() - ((MyObject)m2).getTotalEnergy();
....
}
司马璞
2023-03-14

没有引用MyObject。我的猜测是比较器与MyObject.equal不一致。

也就是说,你违反的合同是:

(comparator.compare(mo1, mo2) == 0) == mo1.equals(mo2)

您的比较器将比较具有相同浮点值的对象作为相等,其中更复杂的比较仪将给出排序,而equals方法将表示对象不相等。或者你可能会遇到相反的问题——equals方法表示对象相等,而compare方法表示对象不同。

以下应该有效。

public int compare(MyObject m1, MyObject m2) {
    if (m1 == m2) return 0;
    if (m1 == null) return -1;
    if (m2 == null) return 1;
    if (m1.equals(m2)) return 0;

    int value = Float.compare(m1.getTotalEnergy(), m2.getTotalEnergy());
    if (value != 0) return value;

    // Warning, this line is not fool proof as unequal objects can have identical hash 
    // codes.
    return m1.hashCode() - m2.hashCode();
}
陈坚
2023-03-14

假设getTotalEnergy()return(s)float,您可以使用

return new Float(m1.getTotalEnergy()).compareTo(m2.getTotalEnergy());

使用 Float.valueOf(float) 可能效率更高,希望这更容易阅读。

Float f1 = Float.valueOf(m1.getTotalEnergy());
Float f2 = Float.valueOf(m2.getTotalEnergy());
return f1.compareTo(f2);
 类似资料:
  • 是的,我知道有很多问题与相同的问题,但我似乎真的找不到我的比较器有什么问题。 所以,这里是: 代码非常简单:我需要根据它们如何改变我的主要结构对一些对象进行排序,并且我首先想要最高值。 由于计算或对象的影响可能需要一些时间,我只是缓存值以便重用它们,因此在排序之前,我检查是否有缓存值或是否需要计算它。 一旦我计算出将< code>m1或< code>m2应用于我的结构的结果,我就将更改恢复。 你可

  • 我有一个类字段,和。我需要使用对它们进行排序,但我得到了一个异常: java.lang.IllegalArgumentException:比较方法违反了它的一般约定! 我的< code>compareTo方法: 请帮我找出compareTo方法中的错误。谢了。

  • 我在尝试对节点的数组列表进行排序时遇到了这个错误。我尝试了大多数解决方案,但没有一个在我的案例中有效。 此代码为 它适用于小输入,但是当输入数量很大时,它会给出这个错误。我也读过比较方法中的传递性规则,但我不知道它是如何在这种情况下应用的。 先谢谢你。

  • 我目前正在Java中对集合进行排序。我收到了错误消息“比较方法违反了它的一般契约”。我也理解这个错误消息,但我(主要)使用Long类型的构建比较方法。所以我不知道,在这种情况下,排序方法仍然违反了契约。这是我的代码: 这里是错误:

  • 从昨天开始,我的代码中出现了错误,我不知道为什么!我用谷歌搜索了很多,找到了这个堆栈帖子。 我使用这个功能按名称对用户进行排序并创建日期。这个功能已经工作了2年,现在我收到一个用户的错误,我不知道发生了什么变化。我试图检查我的数据是否有任何损坏,但找不到任何问题。 读完zhe Stack-Post后,我仍然没有完全理解问题出在哪里,或者我的项目发生了什么变化。

  • 我看到我的应用程序在一些中国 Android 手机上发生了很多崩溃,并出现错误:比较方法违反了其总合同! 我读过这与Collections.sort有关。 我不太确定的是,这是否是因为我的自定义比较器。 以下是错误发生的地方: 比较器是这样的: 所以我不太确定比较器是否搞砸了什么,或者我是否需要以不同的方式进行collections.sort调用 感谢任何帮助