1. HashMap 的 treeifyBin 阈值 8 与扩容阈值 0.75 的设计依据分别是什么?
请说明 HashMap 的 treeifyBin 阈值 8 与扩容阈值 0.75 的设计依据?
- 树化阈值 8 的泊松分布依据
- 负载因子 0.75 的权衡
- 树与扩容的触发
树化阈值 8:当链表长度达到 8 且数组长度达到 64 时树化。依据是泊松分布——在理想哈希下,哈希冲突导致链表长度到达 8 的概率极低(约千万分之六),可认为正常场景不会出现,出现 8 说明哈希分布严重异常,此时用红黑树 O(log n) 替代链表 O(n) 更优。负载因子 0.75:在"空间利用率"与"冲突概率"之间权衡——0.75 时,理想情况下节点分布均匀,桶中结点数在 8 以上的概率极小;若负载因子太高(如 1)空间利用率高但冲突多、查找变慢,太低则频繁扩容浪费空间。0.75 是经验上时间与空间的平衡点。
阈值 8 来自泊松分布统计,保证正常哈希下几乎不会树化;0.75 是时间与空间的折中,扩容前桶的期望数量为 0.75*capacity,能较好控制冲突。两者都服务于"哈希分布良好时用链表,异常时用树/扩容"。
// JDK 源码常量
static final int TREEIFY_THRESHOLD = 8; // 链表树化阈值
static final float DEFAULT_LOAD_FACTOR = 0.75f; // 负载因子