java异常:比较方法违反了其一般合同

时间:2015-01-15 22:28:51

标签: java comparator compareto

我之前已经检查了此主题的帖子 - thisthis。尽管如此,我还是无法弄清楚合同违规在我的代码中是如何发生的。

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方法,不应该照顾合同吗?使调试变得困难的另一个原因是这种异常并不总是发生;只在某些运行期间发生。这可能是什么错误?

提前致谢。

2 个答案:

答案 0 :(得分:3)

由于条目值(分数)会同时更改,因此排序操作期间排序顺序会发生变化。

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

答案 1 :(得分:0)

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

但是,如果您的密钥不同但价值相同,那么这两个密钥会a.compareTo(b)==0,但a.equals(b)将是false