如何处理相同的哈希与相同的密钥?
Posted
技术标签:
【中文标题】如何处理相同的哈希与相同的密钥?【英文标题】:How are same hash vs same key handled? 【发布时间】:2017-12-07 11:53:30 【问题描述】:这个问题不针对任何编程语言,我对通用逻辑更感兴趣。
通常,关联映射采用一个键并将其映射到一个值。据我所知,实现要求键是唯一的,否则值会被覆盖。好的。
所以让我们假设以上是通过一些哈希实现来完成的。 如果两个不同的键获得相同的哈希值怎么办?我正在以底层数组的形式考虑这一点,其索引是所述键上的哈希结果。有可能不止一个唯一键映射到相同的值是吗?如果是这样,这样的实现如何处理这个问题? 处理 same hash 与处理 same key 有何不同?由于 same key 会导致覆盖,并且 same hash 必须保留该值。 我了解带有冲突的散列,所以我知道链接和探测。实现是否会遍历散列到特定索引的当前值并确定键是否相同? 在寻找答案时,我发现了以下链接: 1.What happens when a duplicate key is put into a HashMap? 2.HashMap with multiple values under the same key 然而,他们没有回答我的问题。我们如何区分相同的哈希和相同的键?
【问题讨论】:
【参考方案1】:通过比较键。如果您查看哈希映射的面向对象实现,您会发现它们通常需要在键类型上实现两种方法:
bool equal(Key key1, Key key2);
int hash(Key key);
如果只能给出哈希函数而没有相等函数,则将哈希映射限制为基于语言的默认相等。这并不总是可取的,因为有时需要将键与不同的相等函数进行比较。例如,如果键是字符串,应用程序可能需要进行不区分大小写的比较,然后它会传递一个在散列之前转换为小写的散列函数,以及一个忽略大小写的相等函数。
哈希映射将键与每个对应的值一起存储。 (通常,这是指向最初存储的键对象的指针。)任何对哈希映射的查找都必须在找到匹配的哈希后进行键比较,以验证键是否实际匹配。
例如,对于在每个存储桶中存储一个列表的非常简单的哈希映射,该列表将是(键,值)对的列表,并且任何查找都会比较每个列表条目的键,直到找到匹配项。在伪代码中:
Array<List<Pair<Key, Value>>> buckets;
Value lookup(Key k_sought)
int h = hash(k_sought);
List<Pair<Key, Value>> bucket = buckets[h];
for (kv in bucket)
Key k_found = kv.0;
Value v_found = kv.1;
if (equal(k_sought, k_found))
return v_found;
throw Not_found;
【讨论】:
【参考方案2】:您无法从索引中判断键是什么,因此您不能遍历值以查找有关键的任何信息。您要么必须保证 0 次冲突,要么存储经过哈希处理的信息以提供索引。
如果您的结构中仅存储值,则无法判断它们是否具有相同的键或只是相同的散列。您需要将密钥与要知道的值一起存储。
【讨论】:
以上是关于如何处理相同的哈希与相同的密钥?的主要内容,如果未能解决你的问题,请参考以下文章
如何处理 Template Toolkit 中包含非法标识符字符的哈希键?