java异常:比较方法违反了它的一般契约

java exception: Comparison method violates its general contract

我已经查看过有关此主题的先前帖子 -- this and this。尽管如此,我无法弄清楚在下面给出的代码中如何发生违反合同的情况。

public class ScoreComparator 
implements Comparator<Map.Entry<?, Double>> {

public int compare(Map.Entry<?, Double> o1, 
        Map.Entry<?, Double> o2) {
    return o1.getValue().compareTo(o2.getValue());
}   
}

我的使用方式如下:

List<Entry<String, Double>> entryList = 
        new ArrayList<Entry<String, Double>>(
                iterTypeScoreMap.get(keyToSort).entrySet());
Collections.sort(entryList, new ScoreComparator());

并且iterTypeScoreMap声明如下

ConcurrentHashMap<String, Map<String, Double>> iterTypeScoreMap;

映射 (iterTypeScoreMap) 可以在排序过程中更改,这就是为什么我制作了列表的副本然后对其调用排序的原因。

因为我使用的是 Double 的内置 compareTo 方法,难道不应该处理契约吗?使调试变得困难的另一件事是这种异常并不总是发生。仅在某些运行期间发生。这里的错误可能是什么?

提前致谢。

我认为问题是 a.compareTo(b)==0 应该暗示 a.equals(b)

但是,如果您的密钥不同但值相同,则两者将 a.compareTo(b)==0a.equals(b) 将是 false

发生的事情是,由于条目值(分数)同时更改,您的排序顺序在排序操作期间发生了变化。

当条目本身被同时修改时,复制地图的 entrySet() 没有帮助。您必须深复制集合,换句话说,还要复制所有 Entry 对象,以防止出现错误。就目前而言,您正在排序的列表引用了与原始地图相同的 Entry 对象。