有没有理由在Java Hashmap中使用8 on TREEIFY_阈值?

有没有理由在Java Hashmap中使用8 on TREEIFY_阈值?,java,hashmap,Java,Hashmap,从Java8开始,hashMap稍作修改,如果同一个bucket上的项目超过8个(TREEIFY_THRESHOLD=8),则使用平衡树而不是linkedlist。有什么理由选择8吗 如果是9,它会影响性能吗?使用平衡树而不是链表是一种折衷。对于列表,必须执行线性扫描以在bucket中执行查找,而树允许日志时间访问。当列表很小时,查找速度很快,使用树实际上并没有带来好处,而大约8个元素的列表中查找的成本变得足够大,以至于树提供了一个加速 我怀疑使用树是为了特殊情况,即密钥散列被灾难性破坏(例如,

从Java8开始,hashMap稍作修改,如果同一个bucket上的项目超过8个(TREEIFY_THRESHOLD=8),则使用平衡树而不是linkedlist。有什么理由选择8吗


如果是9,它会影响性能吗?

使用平衡树而不是链表是一种折衷。对于列表,必须执行线性扫描以在bucket中执行查找,而树允许日志时间访问。当列表很小时,查找速度很快,使用树实际上并没有带来好处,而大约8个元素的列表中查找的成本变得足够大,以至于树提供了一个加速

我怀疑使用树是为了特殊情况,即密钥散列被灾难性破坏(例如,许多密钥冲突);虽然线性查找会导致性能严重下降,但使用树可以缓解这一问题 如果关键点具有直接可比性,则性能会有所下降

因此,8个条目的确切阈值可能不太重要:假设密钥分布良好,则树库的概率为0.00000006,因此在这种情况下,显然很少使用树库。当散列算法灾难性地失败时,bucket中的密钥数无论如何都远远大于8

由于树节点必须包含额外的引用,因此这会带来空间损失:除了
LinkedHashMap.Entry
(请参阅)的字段外,还必须包含四个对树节点的引用和一个布尔值

从:

因为树节点的大小大约是常规节点的两倍,所以我们 仅当容器包含足够的节点以保证使用时才使用它们 (参见树型阈值)。当它们变得太小时(由于 移除或调整大小)它们被转换回普通垃圾箱。在里面 使用分布良好的用户哈希代码、树状容器 很少使用。理想情况下,在随机哈希码下 箱中的节点遵循泊松分布 ()带着 默认调整大小的参数平均约为0.5 阈值为0.75,但由于 调整粒度。忽略方差,则为预期值 列表大小k的出现次数为(exp(-0.5)*pow(0.5,k)/ 阶乘(k))


使用平衡树而不是链表是一种折衷。对于列表,必须执行线性扫描以在bucket中执行查找,而树允许日志时间访问。当列表很小时,查找速度很快,使用树实际上并没有带来好处,而大约8个元素的列表中查找的成本变得足够大,以至于树提供了一个加速

我怀疑使用树是为了特殊情况,即密钥散列被灾难性破坏(例如,许多密钥冲突);虽然线性查找会导致性能严重下降,但使用树可以缓解这一问题 如果关键点具有直接可比性,则性能会有所下降

因此,8个条目的确切阈值可能不太重要:假设密钥分布良好,则树库的概率为0.00000006,因此在这种情况下,显然很少使用树库。当散列算法灾难性地失败时,bucket中的密钥数无论如何都远远大于8

由于树节点必须包含额外的引用,因此这会带来空间损失:除了
LinkedHashMap.Entry
(请参阅)的字段外,还必须包含四个对树节点的引用和一个布尔值

从:

因为树节点的大小大约是常规节点的两倍,所以我们 仅当容器包含足够的节点以保证使用时才使用它们 (参见树型阈值)。当它们变得太小时(由于 移除或调整大小)它们被转换回普通垃圾箱。在里面 使用分布良好的用户哈希代码、树状容器 很少使用。理想情况下,在随机哈希码下 箱中的节点遵循泊松分布 ()带着 默认调整大小的参数平均约为0.5 阈值为0.75,但由于 调整粒度。忽略方差,则为预期值 列表大小k的出现次数为(exp(-0.5)*pow(0.5,k)/ 阶乘(k))


在log(N)