设计哈希函数的核心目标是:把任意长度的输入,快速、均匀地映射到一个固定范围的整数(通常是 0~N-1),同时尽量避免冲突(collision)。下面从设计原则 → 常见方法 → 实战示例 → 常见坑系统讲一下。
同一个输入,必须永远得到同一个哈希值
否则哈希表、缓存、签名都会失效。
计算要快
理想情况:O(1) 或 O(输入长度),不能太复杂。
输出值应尽量均匀分布
否则会导致:
✅ 好的哈希函数 = 让数据“看起来像随机数”
输入哪怕改 1 个 bit,输出也要尽量不同
这能防止“相似输入聚集在一起”。
hash(key) = key mod N
✅ 适合:
❌ 缺点:
hash(key) = floor( N * ( (key * A) mod 1 ) )
常用:
A ≈ 0.6180339887(黄金比例)
适合整数、浮点数。
hash = 0
for c in str:
hash = hash * P + c
常用:
P = 31 或 131
➕ 最后再取模:
hash = hash mod N
✅ Java hashCode() 就是类似思想
int hash = 0;
for (char c : str.toCharArray()) {
hash = (hash * 31 + c) & 0x7fffffff;
}
hash ^= (hash << 5) | (hash >> 27);
✅ 特点:
static int hash(int key) {
key ^= (key >>> 20) ^ (key >>> 12);
return key ^ (key >>> 7) ^ (key >>> 4);
}
int hash(String s, int N) {
int h = 0;
for (int i = 0; i < s.length(); i++) {
h = h * 31 + s.charAt(i);
}
return h % N;
}
class Person {
String name;
int age;
public int hashCode() {
return Objects.hash(name, age);
}
}
✅ 选质数
N = 101, 1009, 10007, 100003
原因:
✅ 动态扩容时:
α ≈ 0.75hash = key % 10
如果 key 是 10 的倍数 → 全冲突
hash = hash % N; // 可能为负
✅ 正确:
hash = (hash & 0x7fffffff) % N;
hash = name.hashCode(); // 忽略 age
✅ 不用自己写的情况
Objects.hash()std::hash✅ 需要自己设计的情况
好的哈希函数 = 快 + 均匀 + 稳定
如果你愿意,可以告诉我:
我可以直接帮你定制一个最合适的哈希函数。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。