首先了解hashmap以了解哈希码
为什么HashCode将31用作乘法?
哈希码源代码
关于分配列表,即哈希,也有一个非常重要的一点,即尽可能地进行数据分配。只要以这种方式,就可以减少哈希碰撞数量。
Hashmap首先出现在JDK 1.2中,并基于Laidial Algorithm.hashmap实现了基础层,允许null键和空值。计算键的哈希值时,null键哈希值为0.hashmap不保证钥匙值对的顺序,这意味着键值对的顺序可能会在某些操作后发生变化。Hashmap是一个非线程安全类,在多线程环境中可能会出现问题。
随着几代人的优化更新,到目前为止,它的源代码部分已经复杂,并且涉及许多知识点。在JDK 1.8中,它包括:1。处置列表实现,2。干扰功能,3。初始化容量,4,4。4,4,4。载荷因子,5,容量扩展元件拆分,6,链接的链接树,7,7,,红树和黑树,8,插入,9,搜索,10,删除,11,遍历,12,段锁,等等。
简单的分发存储通过哈希计算每个字符串元素的索引位置,并将其存储到数组中。
黄色索引ID是没有存储元素的元素存储和绿色索引ID,红色索引ID存储在两个元素中。
问题
1.这里的所有元素都需要获得指数位置,如果元素的位置不够严重,它将失去贷款清单存储的含义,并且不符合预期的性能。
2.在索引ID的计算公式中,数组长度为2的倍数,因此如何初始化此数组大小。
3.阵列越小,碰撞越大,阵列的数量越小,时间和空间就越小。
4.目前,存储了7个元素,并且两个字符串都存储在两个位置中,因此链接列表越来越长。
5.随着元素的继续增加,当数组的长度不足时,如何将原始元素拆分为新位置。
这些问题可以总结为:干扰功能,初始化容量,负载因子,容量扩展方法以及链接的列表和红色黑树转换。
当Hashmap存储元素处理哈希值时,干扰函数具有这样的代码。这是Java 8的扩展运动功能的设计,以优化分布效果。
为什么
从理论上讲,字符串的哈斯码是一个int类型值,可以直接出价为无碰撞的数组。它的长度将近40亿。没有人可以初始化这么大的数组,并且无法放置内存。
我们默认地图的大小为16个长度default_initial_capacity = 1 << 4,所以获取的 Hash 值并不能直接作为下标使用,需要与数组长度进行取模运算得到一个下标值。
那么,hashMap 源码这里不只是直接获取哈希值,还进行了一次扰动计算,(h = key.hashCode()) ^ (h >>> 16)。右侧的哈希值仅是长度长度的一半。之后,它是不同的或用原始哈希值计算的。这将原始哈希值的高和低水平混合在一起,从而增加随机性。
干扰函数的使用是增加随机性,使数据元素更加平衡并减少碰撞。
初始化容量hashmap的默认初始化大小,扩展阵列需要2个倍数的倍数。
初始化的hashmap时,如果传递了第17个值<>(17),将如何处理?
找到2个倍数的最小值
在hashmap的初始化中,有这样的方法
THRSHOLD是通过方法表Zizefor计算得出的,该方法是根据初始化计算的。该方法是找到大于初始值的两个-in生产值,例如最小。例如,应找到17,32。
加载
负载因子可以理解,当汽车的加载超过阈值时,可以将汽车载入新车。然后在哈希姆普中,负载因子决定了扩展多少数据。
这里提到了上面的哈希图示例。我们已经准备了7个元素,但是最终有3个免费的位置,并且有2个元素存储在2个位置。但是大量的碰撞出现在某些小标准位置。您只能存储在同一位置的链接列表中。锁定地图数组的性能。
因此,选择一个合理的尺寸以扩大容量。默认值0.75表示,当阈值的值为3/4时,迅速扩展了减少哈希相撞的能力。在同一时间,0.75是默认的构造函数值。您也可以调整哈希图。例如,如果您想在时间上使用更多的空间,则可以使负载较小的音调减小并减少碰撞。
哈希图数据插入整体过程1.首先,进行哈希干扰以获得新的哈希值。
2.确定选项卡是为空还是长度为0,如果是的,则将执行扩展操作。
3.根据哈希值计算出价。如果未存储相应的小额投标,则可以直接插入,否则需要覆盖。
4.确定标签[i]是否是树节点,否则将数据插入链接列表中,然后将节点插入到树中。
5.如果链接列表插入链接列表中,则链接列表的长度大于8,链接列表需要转换为红树和黑树。
6.完成所有元素的处理后,确定其是否超过阈值;阈值,超过容量时,扩大容量。
7. Treeifybin是在链接列表中转动树的一种方法,但并非所有链接仪表长度为8.要转换为树,有必要判断切断的阵列桶的长度是否小于64 min_tree_capacity。如果您需要扩大容量,则将链接的列表上的数据拆卸并分散在相应的枪管节点上,这将缩短链接列表的长度。
扩展机制哈希图是根据数组+链接列表以及红树和黑树实现的,但是值得存储密钥的阵列桶的长度是固定的,这是由初始化确定的。
然后,随着数据插入的数量增加以及负载因子的效果,需要扩展以存储更多数据。在扩展中,有一个非常重要的点,即JDK1.8中的优化操作。您不能再重新计算每个元素的哈希值。
1.在扩展过程中计算新的新上限和新思想。这些是两个词的缩写,一个是容量,另一个是阀门阈值。
2. NEWCAP用于创新阵列桶新节点[NewCap]。
3.随着扩展,由于缺乏散布和存储在新的位置中,因此存储在链接列表以及红色和黑树中的元素。
链接链接器树数据结构的最大性能是哈希姆普,最大的性能是它可以找到时间复杂性的元素,但是由于哈希碰撞必须在一个出价中存储多个数据集,然后在JDK1.8之前设计仅以链接的方式存储。如果您需要从链接列表找到数据的数据时间复杂性,则链接列表越长,性能越糟。红树结构以优化定位元件的时间复杂性类似于O(logn),以提高元素搜索效率的效率,它并没有完全放弃链接列表,因为当元素相对较小,相对较小,链接列表的插入速度更快,因此设置阈值为8至8,以执行红色和黑色树转换操作。
1.链接列表的条件有两个点:链接列表的长度大于8,枪管的容量大于64,否则只会扩大容量并且不会树。
2.在链接列表的树木化过程中,链接列表首先转换为树节点。目前,树可能不是平衡树。在同一时间,将在树转换过程中记录链接列表的顺序,tl.next = p,主要方便后续树-to -linked链接列表和分裂。
3.在将链接列表转换为树之后,将红树和黑树转换为简短的介绍,红树的转换需要染色和旋转,并进行比较。在比较元素的大小上,有一个更有趣的方法。决胜顺序加班,这主要是因为Hashmap没有像Treemap这样的比较器的实现。
在转换树的过程中,红色树木过渡链记录了原始链接列表的顺序。嗯,这很简单。当红树和黑树在链接列表中时,您可以将treenode直接转换为节点。