从Java 8开始,如果在同一存储桶中有8个以上的项目(TREEIFY_THRESHOLD = 8),hashMap会稍作修改以具有平衡树而不是链表。有什么理由选择8吗?
如果是9,会影响性能吗?
答案 0 :(得分:1)
使用平衡树而不是链接列表是一种折衷。对于列表,必须执行线性扫描以在存储桶中执行查找,而树允许进行日志时间访问。当列表较小时,查找速度很快,并且使用树实际上并没有带来好处,而大约8个元素时,列表中查找的成本变得足够大,以至于树可以提供加速。
我怀疑树的使用是为了特殊情况下的,即密钥哈希被灾难性地破坏(例如,许多密钥冲突);而线性查找会导致性能严重下降,使用树可以缓解这种情况 性能会有所损失,如果 if 键可以直接比较。
因此,确切的8个条目阈值可能并不十分重要:假设密钥分配良好,则树箱的概率为0.00000006,因此显然在这种情况下很少使用树箱。当哈希算法灾难性地失败时,存储桶中的密钥数无论如何都远远大于8。
这会占用空间,因为树节点必须包含其他引用:除LinkedHashMap.Entry
的字段之外,对树节点的四个引用和一个布尔 (请参阅{{ 3}})。
来自its source:
由于TreeNode的大小约为常规节点的两倍,因此 仅在垃圾箱包含足以保证使用的节点时才使用它们 (请参阅TREEIFY_THRESHOLD)。当它们变得太小时(由于 移除或调整大小),它们会转换回普通垃圾箱。在 分布良好的用户hashCode的用法 很少使用。理想情况下,在随机hashCodes下, 箱中的节点遵循泊松分布 (comments in the HashMap class source)与 默认调整大小的平均参数约为0.5 阈值0.75,尽管由于 调整粒度。忽略差异,预期 列表大小k的出现是(exp(-0.5)* pow(0.5,k)/ 阶乘(k)。