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

时间:2015-01-27 18:32:18

标签: java sorting

是的,我知道同样的问题有很多问题,但我似乎无法找到比较器出了什么问题。

所以,这是:

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对象的影响可能需要一些时间,我只是缓存值以便重用它们,因此,在排序之前,我检查是否有缓存值或者是否我需要计算它。

一旦我计算了将m1m2应用于我的结构的结果,我就会将更改还原。

您可以将此视为从AI世界中进行的某种评估排序: 我想根据我应用它们的棋盘分数对动作进行排序。

你对此有什么想法吗?

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

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 个答案:

答案 0 :(得分:1)

这并不完全算作比较器实现的简单代码。很多事情都可能出错,并且没有显示关键代码(doSomethingundoSomething)。从它的外观来看,m1m2是可变对象,如果它们发生变化使得它们与较早时间不相等,则排序算法会中断。我认为这是您错误的最可能解释。

另一种解决问题的方法,无论如何我都会推荐,重新思考你的方法。由于任何排序算法必须至少触摸一次每个值,因此懒惰的初始化方案只会带来复杂性的开销。而是准备一个简单的列表移动,其中的值被烘焙(您需要一个表示移动及其评估的对象),并且仅使用一个不可变对象列表进行排序他们的自然顺序(compareTo的简单实现会做到这一点)。此时,您的错误将留下很少隐藏的地方,并且可能在您完成之前消失。