斐波那契散列函数:
(val * HASH_INCREMENT + HASH_INCREMENT)& (2 ^ n -1)
斐波那契散列增量HASH_INCREMENT,逻辑:黄金分割点:(√5 - 1) / 2 = 0.6180339887,Math.pow(2, 32) * 0.6180339887 = HASH_INCREMENT = 0x61c88647
测试
@Test
public void test_idx() {
Map<Integer, Integer> map = new HashMap<>();
List<Integer> fiboList = new ArrayList<>();
List<Integer> normList = new ArrayList<>();
int HASH_INCREMENT = 0x61c88647;
int hashCode = 0;
for (int i = 1; i <= 100; i++) {
hashCode = i * HASH_INCREMENT + HASH_INCREMENT;
int idx = hashCode & (128 - 1);
fiboList.add(idx);
map.merge(idx, 1, Integer::sum);
int normIdx = String.valueOf(i).hashCode() & (128 - 1);
normList.add(normIdx);
System.out.println("斐波那契散列:" + idx + " 普通散列:" + normIdx);
}
Map<Integer, Long> duplicatesFibo = fiboList.stream()
.collect(Collectors.groupingBy(e -> e, Collectors.counting()));
duplicatesFibo.entrySet().removeIf(entry -> entry.getValue() == 1);
Map<Integer, Long> duplicatesNorm = normList.stream()
.collect(Collectors.groupingBy(e -> e, Collectors.counting()));
duplicatesNorm.entrySet().removeIf(entry -> entry.getValue() == 1);
System.out.println("斐波那契散列冲突索引: " + duplicatesFibo + " 普通散列冲突索引:" + duplicatesNorm);
System.out.println(map);
}
测试结果
测试结果会发现,斐波那契散列会分布的更加均匀,普通散列会出现连续的哈希值
发现对于数据量 nums < 2 ^ n - 1 斐波那契没有产生冲突,而普通散列会产生大量的哈希碰撞
Java中的ThreadLocal中采用了斐波那契散列+开放寻址方式存放Entry
开放寻址:为了减少哈希碰撞,从碰撞点开始,寻找空槽进行插值。