我之前已经检查了此主题的帖子 - this和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方法,不应该照顾合同吗?使调试变得困难的另一个原因是这种异常并不总是发生;只在某些运行期间发生。这可能是什么错误?
提前致谢。
答案 0 :(得分:3)
由于条目值(分数)会同时更改,因此排序操作期间排序顺序会发生变化。
当条目本身被同时修改时,制作地图entrySet()
的副本没有帮助。您必须深度复制集合,换句话说,复制所有Entry
对象,以防止出错。就目前而言,您正在排序的列表引用了与原始地图相同的Entry对象。
答案 1 :(得分:0)
我认为问题在于a.compareTo(b)==0
应该暗示a.equals(b)
。
但是,如果您的密钥不同但价值相同,那么这两个密钥会a.compareTo(b)==0
,但a.equals(b)
将是false
。