Luk*_*Feo 10 java hash hashmap hashcode hashset
在Hashmap中,提供的密钥的哈希码用于将值放在哈希表中.在Hashset中,obects哈希码用于将值放在底层哈希表中.也就是说,hashmap的优点是你可以灵活地决定你想要什么作为键,这样你就可以做到这样的好事.
Map<String,Player> players = new HashMap<String,Player>();
Run Code Online (Sandbox Code Playgroud)
这可以将诸如玩家名称之类的字符串映射到玩家本身.
我的问题是当密钥的Hashcode发生变化时,查找会发生什么.
我希望这不是Hashmap的主要问题,因为我不希望也不希望密钥发生变化.在前面的例子中,如果球员名称发生变化,他就不再是那个球员了.但是我可以使用密钥更改其他不是名称的字段来查看播放器,将来的查找将起作用.
但是在Hashset中,由于整个对象的哈希码用于放置项目,如果某人略微更改了对象,则该对象的未来查找将不再解析为Hashtable中的相同位置,因为它依赖于整个对象Hashcode.这是否意味着一旦数据在Hashset中就不应该被更改.还是需要重新加入?还是自动完成等?到底是怎么回事?
Ste*_*n C 17
在您的示例中,String是不可变的,因此其哈希码不能更改.但假设,如果对象的哈希码确实发生了变化而哈希表中的键是关键,那么就哈希表查找而言,它可能会消失.我在这个相关问题的答案中详细介绍了:https: //stackoverflow.com/a/13114376/139985.(最初的问题是关于a HashSet,但是a HashSet真的是一个HashMap封面,所以答案也涵盖了这个案例.)
它是安全地说,如果任何一个HashMap或映像树的钥匙,影响他们各自的方式突变hashcode()/ equals(Object)或compare(...)或compareTo(...)合同,则数据结构将"打破".
这是否意味着一旦数据在Hashset中就不应该被更改.
是.
还是需要重新加入?还是自动完成等?
它不会自动重新散列.该HashMap不会注意到一个关键的哈希码已经改变.实际上,在HashMap调整大小时,您甚至不会重新计算哈希码.数据结构记住原始哈希码值,以避免在哈希表调整大小时重新计算所有哈希码.
如果您知道密钥的哈希码将要更改,则需要在更改密钥之前从表中删除该条目,然后将其添加回来.(如果在改变密钥后尝试remove/ put它,很remove可能无法找到条目.)
到底是怎么回事?
发生的事情是你违反了HashMapjavadocs中明确规定的合同.不要那样做!