把复杂键转换为可用数值

字符串或复合键不一定能直接当作数组下标。哈希函数按规则把它们转换为整数,再按表的大小映射到允许的桶位置,使查找先集中到较小的一组候选。相同键在同一套函数参数下,需要得到一致结果。

有限的输出范围通常无法为更大的输入集合保证逐一不同,因此不同键可能碰撞。哈希值相等并不证明原值相同;哈希表仍要根据自己的相等契约比较候选,并采用链表或探测等方式处理相同桶位置。

参考:[1]

分布与计算成本共同影响效果

只取键的一小部分,可能把相似输入大量挤到同一位置。例如忽略字符串中真正变化的部分,就会留下很多碰撞。设计函数通常希望兼顾计算方便,以及让实际键在输出范围中分布得较分散。

均匀分布是某些分析采用的假设或设计目标,不是对任意输入集合的自动承诺。字符串很长时,读取输入本身也需要时间;不能只因最终得到一个固定宽度整数,就把整个哈希过程当作与输入长度无关的操作。

参考:[1]

种子与安全用途另有约定

一些哈希函数还接收种子,同一个输入在不同种子下可以获得不同映射。Go的maphash建议不同哈希表或数据结构采用各自的种子;在需要复现结果时,必须同时说明所用种子与接口约定,而不只保存输入文字。

适合哈希表的函数也未必适合密码学用途。maphash文档明确说明其函数不具备密码学安全性。选型应依据实际目标:快速定位桶、保持查找相等关系,与要求抗碰撞或其他安全性质,不是仅由“哈希”这个名称共同保证的能力。

参考:[2]