Java 自定义键对象应该是不可变的吗?如果是,为什么?
好的,我想在我的Java 自定义键对象应该是不可变的吗?如果是,为什么?,java,collections,immutability,Java,Collections,Immutability,好的,我想在我的HashMap中使用自定义的用户定义对象作为键,而不是说String。候选对象应该是不可变的吗?我在某个地方读到,最好的做法是使它们不变,但我自己也不知道原因 是的,它们应该是不可变的,因为如果可以更改,它们就不能像键一样正常工作。想象一下,为你的房子买了一把锁和钥匙,然后决定把钥匙锤成不同的形状,让它更漂亮。这不太好用,是吗?这里也适用同样的原则。如果HashMap中有一个可变键,那么它最终将进入错误的存储桶,这将完全破坏映射 插入键,调用hashCode(),指定bucket
HashMap
中使用自定义的用户定义对象作为键,而不是说String
。候选对象应该是不可变的吗?我在某个地方读到,最好的做法是使它们不变,但我自己也不知道原因 是的,它们应该是不可变的,因为如果可以更改,它们就不能像键一样正常工作。想象一下,为你的房子买了一把锁和钥匙,然后决定把钥匙锤成不同的形状,让它更漂亮。这不太好用,是吗?这里也适用同样的原则。如果HashMap中有一个可变键,那么它最终将进入错误的存储桶,这将完全破坏映射
如果您在树映射中有一个可变键,那么它将最终位于树的错误位置,这应该是排序的(这发生在插入时)。与上述流程基本相同
因为我们喜欢这里的明喻,这就像在现有的电话簿上用一个神奇的记号笔更改你的名字,而不打印一本全新的书:所以你的新名字“史密斯”仍将列在“约翰”和“约翰斯顿”之间(没有人会去寻找它),也没有人会在“斯马特”和“史密斯”之间(他们正在寻找它). TreeMap就像电话簿一样工作。是的。如果从其他地方更新密钥,则无法再查找为该密钥存储的值。您的意思是使用原始密钥而不是更改的密钥进行查找,对吗?使用更改的密钥进行查找将导致存储区为空。按原始键查找将找到一个条目,但它不再是
相等的
。两种情况下都有错误。在步骤4中,如果发现的值不相等,则我们根本不接触该值。我们刚刚在步骤2中更改了键?旧值不等于新值。所谓价值,我指的是关键。将使用更清晰的措辞进行编辑。如果在哈希表中存储密钥时,任何代码都不会接收到对该密钥的引用,则可以在哈希表中轻松地拥有可变类型的密钥。如果希望允许表中存在对象的“实时视图”,并且不使用多线程,那么让表引用的对象真正可变可能会有所帮助,但提供某种形式的更新通知,以便每次更改都将从表中删除旧项并添加新项。如果hashCode
和/或equals
可以在关键对象生存期内更改,则违反了HashMap
工作所需的不变量。虽然键集
、值
和入口集
仍将分别包含与键值对对应的键、值和映射项,但不能保证哈希映射
在查询时能够找到与该键相关联的值。