斐波那契散列属于乘法散列的一种特例,通过该算法可以减少hash冲突的发生。其核心原理是利用黄金分割比(约0.618)来构造哈希函数。
ThreadLocal底层使用ThreaLocalMap存储数据,存储数据时,就是使用斐波那契散列计算key的索引。
适用场景
促销活动:为每个用户生成唯一优惠码,避免重复领取。
抽奖系统:生成公平的抽奖号码,确保概率均等。
缓存路由:在数据库索引或缓存系统中,提升查询效率。
主要优势:
分布均匀性:利用黄金分割比的数学特性,能够使哈希值在地址空间中分布更加均匀
减少冲突:相比传统除法散列,能有效降低哈希冲突概率
计算效率:在硬件实现上通常只需要一次乘法和位移操作,效率较高
算法:
index = (v* HASH_INCREMENT + HASH_INCREMENT) & (length - 1)
注意:
0.6180339887:黄金分割点,计算公式是(√5 - 1)/2
HASH_INCREMENT:Math.pow(2, 32) * 0.6180339887 = 0x61c88647
该值相当于有符号整数的黄金分割值
length表示最大的数组长度,必须是2^n
测试代码1:
数组长度128,相当于2^8
@Test
void testHash() {
Integer[] testArr = new Integer[128];
for (int i = 0; i < 100; i++) {
int hashCode = i * 0x61c88647 + 0x61c88647;
int index = hashCode & (128 - 1);
if (testArr[index] != null) {
System.out.println("发生碰撞索引:" + index);
} else {
testArr[index] = i;
}
}
}
运行后不会有hash冲突
测试代码2:
@Test
void testHash() {
Integer[] testArr = new Integer[110];
for (int i = 0; i < 100; i++) {
int hashCode = i * 0x61c88647 + 0x61c88647;
int index = hashCode & (110 - 1);
if (testArr[index] != null) {
System.out.println("发生碰撞索引:" + index);
} else {
testArr[index] = i;
}
}
}
运行后会有hash冲突

经过多次测试,计算索引时,length长度必须是2^n(本博客只展示了部分测试代码,读者可以自行测试其他长度)
1570

被折叠的 条评论
为什么被折叠?



