问题描述
考虑以下场景:
Object o1 = new Object();
Object o2 = new Object();
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put(o1, o2);
boolean test1 = map.get(o1) == o2; // This evaluates to true
// Now lets say we alter the state of o1:
o1.setSomeInternalState(Object newState);
boolean test2 = map.get(o1) == o2; // This evaluates to false, because now map.get(o1) returns null
假设 o1 的类已覆盖 equals()
和 hashCode()
.
Assume that the class for o1 has overridden equals()
and hashCode()
.
我在调试过程中遇到了这个问题,因为我在某些业务逻辑中使用的一个特定对象上明确覆盖了 equals
和 hashCode
.我可以完全理解为什么当我改变它的状态时对象的哈希码会改变,但是为什么 map.get(o1) 会因为它返回 null 呢?只有一个对象,所以key的hashcode不应该匹配吗?
I've encountered this issue during debugging because I had explicitly overridden equals
and hashCode
on one particular object I'm using in some business logic. I can fully appreciate why the hashcode of the object changes when I alter its state, but why should the map.get(o1) return null because of it? There is only one object, so shouldn't the key's hashcode match?
推荐答案
HashMap
类通过 运行键的 hashCode
将键映射到值哈希函数.哈希函数用于创建桶数组的索引.例如,very 原始散列函数将是 hashCode % tableSize
.更改键的 hashCode
会更改哈希函数创建的索引,这意味着在该存储桶中找不到任何内容.
The HashMap
class maps keys to values by running the hashCode
of the key through a hash function. The hash function is used to create an index into an array of buckets. For example, a very primitive hash function would be hashCode % tableSize
. Changing the key's hashCode
would alter the index created by the hash function, meaning there is nothing to be found in that bucket.
我们运行一个例子,假设初始hashCode
为15,表大小为4:
Let's run an example, assuming that the initial hashCode
is 15 and the table size is 4:
┌----------------------┐
15 (initial hashCode) -> | hashCode % tableSize | -> index 3
| (hash function) |
└----------------------┘
所以让我们在索引 3 处插入值:
So let's insert the value at index 3:
┌------┐
0 | null |
|------|
1 | null |
|------|
2 | null |
|------|
3 | key! | <- insert
└------┘
现在让我们修改密钥的 hashCode
使其现在是 13:
Now let's modifiy the key's hashCode
so that it is now 13:
┌----------------------┐
13 (modified hashCode) -> | hashCode % tableSize | -> index 1
| (hash function) |
└----------------------┘
索引 1 是什么?什么都没有,null
.
What's at index 1? Nothing, null
.
这里已经简化了很多事情.在真正的哈希表实现中,哈希函数要创建更均匀的分布要复杂得多.此外,存储桶是链表,因此可以处理冲突.
A lot of things have been simplified here. In a real hash table implementation, the hash function is much more complex to create a more even distribution. Also, the buckets are linked-lists so collisions can be handled.
这篇关于为什么更改用作 HashMap 中键的对象的哈希码会使查找返回 null?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!