减少散列冲突的关键在于重写hashcode方法,需用31等奇素数乘法逐字段计算、缓存不可变key的哈希值、精简equals比较范围,并预设hashmap初始容量。

减少散列冲突的关键不在 Object 类本身——它只提供默认(基于内存地址的)hashCode 实现,真正起作用的是你重写后的 hashCode() 方法。设计目标很明确:让不同业务对象尽可能生成不同、均匀分布的 int 值,同时兼顾计算效率和稳定性。
用奇素数乘法 + 逐字段参与,避免简单拼接
推荐以 31 为乘数(JVM 对 i * 31 会优化为位移加减),从一个非零初值(如 17 或 31)开始,逐个纳入关键字段:
- 字符串字段直接调用
field.hashCode()——它内部已高效实现,无需自己遍历字符 - 数值字段(int/long)直接参与运算;布尔字段转为
field ? 1 : 0 - 枚举建议用
ordinal()(前提是枚举顺序稳定)或预定义整型码 - 避免把多个字段 toString() 后拼接再 hash,这既慢又易撞(如 "123"+"abc" 和 "12"+"3abc" 可能相同)
对长文本或大字段做轻量摘要
如果 key 中含 JSON、HTML 或超长日志文本,全量调用 String.hashCode() 成为性能瓶颈:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 可截取前 64 或 128 字符再 hash,实测对大多数业务区分度足够
- 更稳的做法是用 CRC32 或 MurmurHash3 的轻量版(如
java.util.zip.CRC32),比原生字符串 hash 更抗偏斜 - 完全避开大字段:若该字段不参与业务唯一性判定(如 content),就不应放入 hashCode 计算
缓存不可变 Key 的哈希值
只要你的 key 类是不可变的(必须!),就应在构造时一次性算出 hashCode 并缓存:
- 声明
private final int hashCode; - 构造器中赋值:
this.hashCode = 31 * (31 * id + type.hashCode()) + status; -
hashCode()方法直接 return 该字段,不判空、不锁、不重算 - 实测百万级 put 场景下,避免重复解析字符串,耗时可从 400ms 降至 35ms
配合 equals 精简与容量预设
哈希冲突后,HashMap 会遍历桶内节点调用 equals() ——这部分开销同样关键:
-
equals()只比核心标识字段(如 id、tenantId + bizCode),跳过 createTime、remark 等非区分字段 - 先做引用比较
this == obj,再比 class,再比字段,提升短路效率 - 初始化 HashMap 时按预估 size ÷ 0.75 向上取整到 2 的幂(如 12000 → 16384),避免频繁扩容放大抖动
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










