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)==0
但 a.equals(b)
将是 false
。
发生的事情是,由于条目值(分数)同时更改,您的排序顺序在排序操作期间发生了变化。
当条目本身被同时修改时,复制地图的 entrySet()
没有帮助。您必须深复制集合,换句话说,还要复制所有 Entry
对象,以防止出现错误。就目前而言,您正在排序的列表引用了与原始地图相同的 Entry 对象。
我已经查看过有关此主题的先前帖子 -- 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)==0
但 a.equals(b)
将是 false
。
发生的事情是,由于条目值(分数)同时更改,您的排序顺序在排序操作期间发生了变化。
当条目本身被同时修改时,复制地图的 entrySet()
没有帮助。您必须深复制集合,换句话说,还要复制所有 Entry
对象,以防止出现错误。就目前而言,您正在排序的列表引用了与原始地图相同的 Entry 对象。