核心是让 hashCode 输出更均匀、计算更轻量、结果可复用;Java HashMap虽有扰动函数,但Key类hashCode若低效或分布差则影响整体性能;宜用31等奇素数乘数配合位运算优化。
核心是让 hashcode 输出更均匀、计算更轻量、结果可复用。java 的 hashmap 本身有扰动函数,但若 key 类的 hashcode 实现低效或分布差,再好的底层也救不了。
用奇素数系数 + 位运算组合计算
避免简单拼接或取模。推荐使用 31 作为乘数(JVM 对
会优化为
基础模板:
字符串字段不用
再遍历——它本身已高效;但若字段是长文本或 JSON 字符串,考虑只取前 N 位哈希或摘要(如 CRC32)
数值字段直接参与,布尔用
,枚举用
或自定义稳定码
缓存 hashCode 值,杜绝重复计算
只要 Key 是不可变的(必须!),就应在构造时算一次并存为
:
声明:
构造器中赋值:
方法直接返回该字段,不加锁、不判空、不重算
实测显示:百万级 put 操作中,避免每次调用字符串全量遍历,耗时可从 400ms 降至 35ms
精简 equals 比较范围,降低冲突后开销
哈希冲突发生时,HashMap 会遍历桶内节点调用
。若 equals 过重,性能雪上加霜:
只比对真正用于区分对象的字段,比如业务主键
或
组合
跳过大字段(如
、
)、非标识字段(如
、
)
先做快速筛选:先比引用(
),再比 class,再比核心字段
配合容量预设与负载因子微调
再好的 hash 码,撞上频繁扩容也会放大抖动:
初始化 HashMap 时,按预估元素数 ÷ 0.75 向上取整到 2 的幂(如预估 12000 个 key,初始容量设为 16384)
若业务 key 分布明确偏斜(如 tenantId 集中在几个值),可略调高 loadFactor 到 0.85,减少扩容次数(需权衡空间)
禁止用可变对象(如 ArrayList、Date)作 key;若必须含时间,转为秒级时间戳 long
i * 31i ),逐字段参与运算:result = 31 * result + (field == null ? 0 : field.hashCode());String.hashCode()field ? 1 : 0ordinal()final int hashCodeprivate final int hashCode;this.hashCode = 31 * Objects.hash(id, type) + status;hashCode()equals()idtenantId + bizCodecontentremarkcreateTimeversionthis == obj