如何处理相同的哈希与相同的密钥?

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 次冲突,要么存储经过哈希处理的信息以提供索引。

如果您的结构中仅存储值,则无法判断它们是否具有相同的键或只是相同的散列。您需要将密钥与要知道的值一起存储。

【讨论】:

以上是关于如何处理相同的哈希与相同的密钥?的主要内容,如果未能解决你的问题,请参考以下文章

注销哈希,它们是如何处理的?

在 Perl 中,我如何处理整个哈希?

我该如何处理这个警告:哈希不匹配?

如何处理 Template Toolkit 中包含非法标识符字符的哈希键?

通过 RODBC 通过 RStudio 运行 SQL 查询:如何处理哈希表?

您如何处理公共 git 存储库中的敏感数据?