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

比较方法在排序时违反其一般合同

伍耀
2023-03-14

是的,我知道有很多问题与相同的问题,但我似乎真的找不到我的比较器有什么问题。

所以,这里是:

evaluateComparator = (m1, m2) -> {
    Color color = m1.getColor(); // m1 and m2 will have the same one
    double m1Value, m2Value;
    if (sortingCache.containsKey(m1)) {
        m1Value = sortingCache.get(m1);
    } else {
        // The value has not been computed before so it's not in the cache and I need to compute it now     
        someClass.doSomething(m1);
        m1Value = someClass.getValue();
        someClass.undoSomething(m1);
        sortingCache.put(m1, m1Value);
    }
    if (sortingCache.containsKey(m2)) {
        m2Value = sortingCache.get(m2);
    } else {
        // The value has not been computed before so it's not in the cache and I need to compute it now     
        someClass.doSomething(m2);
        m2Value = someClass.getValue();
        someClass.undoSomething(m2);
        sortingCache.put(m2, m2Value);
    }
    // Since I'm comparing two doubles I can use the Double's comparator
    return Double.compare(m1Value, m2Value);
};

代码非常简单:我需要根据它们如何改变我的主要结构对一些对象进行排序,并且我首先想要最高值。

由于计算m1m2对象的影响可能需要一些时间,我只是缓存值以便重用它们,因此在排序之前,我检查是否有缓存值或是否需要计算它。

一旦我计算出将< code>m1或< code>m2应用于我的结构的结果,我就将更改恢复。

你可以看到这就像是从人工智能世界中提取的某种评估排序:我想根据我应用它们的棋盘得分对动作进行排序。

你对此有什么想法吗?

编辑:由于可能涉及散列和缓存的奇怪事情,我删除了对缓存的所有引用,但我仍然有问题。

evaluateComparator = (m1, m2) -> {
    double m1Value, m2Value;

    someClass.doSomething(m1);
    m1Value = someClass.getValue();
    someClass.undoSomething(m1);

    someClass.doSomething(m2);
    m2Value = someClass.getValue();
    someClass.undoSomething(m2);

    return Double.compare(m1Value, m2Value);
};

共有1个答案

吕俊哲
2023-03-14

对于比较器实现来说,这并不能完全算作简单的代码。很多事情可能会出错,并且没有显示关键代码(do的undo的)。从表面上看,m1m2是可变对象,如果它们发生变化,以至于它们与之前的它们不相等,排序算法就会崩溃。我认为这是对您的错误的最有可能的解释。

解决您的问题的另一种方法是重新考虑您的方法,无论如何我都会推荐。由于任何排序算法都必须至少接触每个值一次,因此延迟初始化方案只会带来复杂性开销。取而代之的是准备一个简单的移动列表,其中包含它们的值(你需要一个表示移动及其评估的对象),并且仅使用它们的自然顺序对这个不可变对象的列表进行排序(compareTo 的简单实现就可以了)。到那时,您的错误将几乎没有隐藏的地方,并且可能会在您完成之前消失。

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

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

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

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

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

  • 下面是导致异常的代码块,如所示, 代码: 例外情况: 当我将相同的代码作为独立程序运行时,该问题从未出现。这里的比较器有什么问题?有没有办法在独立代码中重现该问题? 这个问题只在Java 1.7上出现,因为Arrays.sort上的实现发生了变化