Java TreeMap重复键

时间:2015-03-12 08:32:10

标签: java

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

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

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

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

这是比较器代码:

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;

    }

1 个答案:

答案 0 :(得分:6)

比较器总是需要返回一致的结果,并且在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保持一致的其他标准,因为otherMap.get(s1).compareTo(otherMap.get(s2))可能会返回0,即使s1不等于s2


我在一个自我回答的跟进问题here中对此进行了详细阐述。


来自评论:

  

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

不,当您插入密钥时,TreeMap将使用比较器搜索数据结构以查看密钥是否已存在。如果比较器给出不一致的结果,TreeMap可能查看错误的地方并得出结论:该密钥不存在,导致未定义的行为。