Java 中的哈希(Hash)机制:HashMap 与 Hashtable 的实现对比
哈希(Hash)是 Java 集合框架中实现高效存储和查询的核心机制,尤其是在 HashMap 和 Hashtable 中,哈希算法的设计直接影响哈希冲突的概率和性能。本文将深入解析两者的哈希计算方法、索引定位逻辑及优化策略,揭示其减少哈希碰撞的底层原理。
哈希的核心目标
哈希的核心是通过哈希函数将任意长度的输入(如对象的 hashCode)映射到固定长度的输出(如数组索引),目标是:
- 均匀分布:使键值对在数组中均匀分布,减少哈希冲突(不同键映射到同一索引);
- 高效计算:哈希函数和索引计算应简单快速,避免额外性能损耗。
HashMap 的哈希机制(JDK 1.8)
HashMap 采用 “二次哈希 + 与运算” 的方式,通过扰动函数增强哈希值的随机性,减少冲突。
哈希值计算(扰动函数)
HashMap 对键的原始哈希值(key.hashCode())进行二次处理,代码如下:
1 | static final int hash(Object key) { |
扰动的原因:
- 原始
hashCode是 32 位整数,但数组容量(n)通常较小(默认 16,最大2^30),导致计算索引时仅低log2(n)位有效(高位被忽略)。 - 例如:若两个键的
hashCode高位不同但低位相同,直接使用原始哈希值会导致索引冲突。 - 扰动通过 “高 16 位异或低 16 位”,将高位信息混入低位,增加低位的随机性,减少冲突。
索引计算(与运算)
通过扰动后的哈希值计算数组索引: