我想我可能在Java中发现了一个bug.
我有一个TreeMap,我在其中使用自定义比较器.但是,当我把(键,值)放在已经存在的键上时,它似乎不会覆盖键,从而创建重复的键.我想我已经验证了这一点,因为我尝试过:
System.out.println(testMap.firstKey().equals(testMap.lastKey()));
Run Code Online (Sandbox Code Playgroud)
这打印出真实的.任何人都知道为什么会这样吗?
这是比较器代码:
private class TestComp implements Comparator<String> {
@Override
public int compare(String s1, String s2){
if (s1.equals(s2)) {
return 0;
}
int temp = otherMap.get(s1).compareTo(otherMap.get(s2));
if (temp > 0) {
return 1;
}
return -1;
}
Run Code Online (Sandbox Code Playgroud)
比较器总是需要返回一致的结果,并且在TreeMap中使用时,必须与equals一致.
在这种情况下,您的比较器违反了第一个约束,因为它不一定会给出一致的结果.
示例:例如,如果是otherMap地图
"a" -> "someString"
"b" -> "someString"
Run Code Online (Sandbox Code Playgroud)
那么这两个compare("a", "b")和compare("b", "a")返回-1.
请注意,如果您将实现更改为
if (s1.equals(s2)) {
return 0;
}
return otherMap.get(s1).compareTo(otherMap.get(s2));
Run Code Online (Sandbox Code Playgroud)
你打破了与equals一致的其他标准,因为即使不相等otherMap.get(s1).compareTo(otherMap.get(s2))也可能会返回.0s1s2
我在自我回答跟进质询,阐述了这一位置.
来自评论:
即使比较器给出不一致的结果,Java语言是否仍然不允许重复键?
不,当您插入键时,TreeMap将使用比较器搜索数据结构以查看该键是否已存在.如果比较器给出不一致的结果,TreeMap可能会查找错误的位置并断定该键不存在,从而导致未定义的行为.