Java TreeMap重复键

我想我可能在Java中发现了一个bug。

我有一个TreeMap,我在其中使用自定义比较器。 但是,当我把(键,值)放在已经存在的键上时,它似乎不会覆盖键,从而创建重复的键。 我想我已经validation了这一点,因为我尝试过:

System.out.println(testMap.firstKey().equals(testMap.lastKey())); 

这打印出真实的。 任何人都知道为什么会这样吗?

这是比较器代码:

 private class TestComp implements Comparator { @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; } 

比较器总是需要返回一致的结果,并且在TreeMap中使用时,必须与equals一致。

在这种情况下,您的比较器违反了第一个约束,因为它不一定会给出一致的结果。

示例:例如,如果是otherMap映射

 "a" -> "someString" "b" -> "someString" 

那么compare("a", "b")compare("b", "a")将返回-1


请注意,如果将实现更改为

 if (s1.equals(s2)) { return 0; } return otherMap.get(s1).compareTo(otherMap.get(s2)); 

你打破了与equals一致的其他标准,因为即使s1不等于s2otherMap.get(s1).compareTo(otherMap.get(s2))也可能返回0


我在这里通过一个自我回答的后续问题对此进行了详细阐述。


来自评论:

即使比较器给出不一致的结果,Java语言是否仍然不允许重复键?

不,当您插入一个键时,TreeMap将使用比较器搜索数据结构以查看该键是否已存在。 如果比较器给出不一致的结果,TreeMap可能会查找错误的位置并断定该键不存在,从而导致未定义的行为。