31是首选因其为奇质数,与2的幂次表长无公约数,避免取模扎堆;二进制11111对应2⁵−1,JVM可优化为(result<<5)−result,兼顾哈希均匀性、低冲突率与计算效率。

选 31 是最稳妥的选择,不是凭感觉,而是数学特性和 JVM 实现共同决定的。
为什么 31 是首选
31 是奇质数,和常见哈希表容量(2 的幂次,如 16、32、64)没有公约数,能避免哈希值在取模后扎堆;它的二进制是 11111,对应 2⁵ − 1,JVM 能把 result * 31 自动优化成 (result ,位移加减法比乘法快得多;它大小适中——太小(如 17)对多字段或长字符串“搅不匀”,太大(如 101)容易在 int 范围内过早溢出,丢失高位信息。
其他质数可以吗
可以,但要谨慎:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 29、37、41:和 31 接近,分布效果差异不大,实测标准差略高一点,属于可接受范围
- 2:相当于左移,低位全补 0,多个对象哈希值低位趋同,碰撞率飙升
- 10、15、100:合数,会放大输入中的重复模式(比如字段末位常是 0 或 5),加剧冲突
- 101 及以上:三次乘加就容易溢出,int 截断后高位信息丢失,反而削弱均匀性
怎么正确套用 31 计算
核心公式是:result = 31 * result + fieldHash,注意这些细节:
立即学习“Java免费学习笔记(深入)”;
- 起始值别用 0,推荐设为 1(否则第一个字段为 null 就整轮归零)
- 字段顺序必须固定,且和
equals()中的比较顺序一致 - 数组字段不能直接调用
array.hashCode()(那是内存地址),要用Arrays.hashCode(array) - float/double 先转整型:
Float.floatToIntBits(f)或Double.doubleToLongBits(d) - null 字段统一返回 0,避免 NPE
要不要自己写?还是用工具类
Objects.hash(a, b, c) 底层就是按 31 模式累加,安全省心,适合大多数场景。但它有两点要注意:
- 每次调用都新建一个 Object[] 数组,高频 put 场景可能增加 GC 压力
- 传进去的每个参数都会参与计算,没法跳过某些字段;如果字段含数组,必须提前展开,否则
Objects.hash(arr)仍会用数组引用哈希

















