0

好的,我想将自定义用户定义的对象作为我的键HashMap而不是 say String。候选对象应该是不可变的吗?我在某处读到最好的做法是使它们不可变,但我自己无法弄清楚原因。

4

3 回答 3

6

如果您在 HashMap 中有一个可变键,那么它将最终进入错误的存储桶,这完全破坏了 Map。

  1. 插入键,hashCode() 被调用,桶分配
  2. 改变key,hashCode改变,不再匹配bucket
  3. 通过(新)键查找,hashCode() 导致错误的存储桶,找不到值
  4. 通过(旧)键查找,hashCode()导致“正确”存储桶,但现在找到的键不再存在equal(因为它现在是“新”键),所以它也被丢弃

如果您在 TreeMap 中有一个可变键,那么它将最终位于树的错误位置,该位置应该被排序(并且发生在插入时)。基本上和上面的流程一样。

而且由于我们喜欢这里的明喻,这就像用魔术笔在现有电话簿中更改您的名字而不打印一整本新书:所以您的新名字“Smith”仍将列在“John”和“Johnston”之间(其中没有人会寻找它),也没有人会在“Smart”和“Smithers”(他们正在寻找它的地方)之间找到它。TreeMap 就像电话簿一样工作。

于 2012-08-22T06:37:17.933 回答
5

是的,它们应该是不可变的,因为如果可以更改它们,它们就不能很好地用作键。想象一下为你的房子买了一把锁和钥匙,然后决定你想通过把它锤成不同的形状来让它更漂亮。它不会很好地工作,不是吗?同样的原则也适用于此。

于 2012-08-22T06:34:29.337 回答
0

是的。如果您从其他地方更新密钥,那么您将无法再查找为该密钥存储的值。

于 2012-08-22T06:38:32.457 回答