在线网站开发,wordpress无插件,筑梦网站建设,网站建设需求范本转载自 玻璃猫 程序员小灰众所周知#xff0c;HashMap是一个用于存储Key-Value键值对的集合#xff0c;每一个键值对也叫做Entry。这些个键值对#xff08;Entry#xff09;分散存储在一个数组当中#xff0c;这个数组就是HashMap的主干。
HashMap数组每一个元素的初始值都…转载自 玻璃猫 程序员小灰众所周知HashMap是一个用于存储Key-Value键值对的集合每一个键值对也叫做Entry。这些个键值对Entry分散存储在一个数组当中这个数组就是HashMap的主干。
HashMap数组每一个元素的初始值都是Null。对于HashMap我们最常使用的是两个方法Get 和 Put。1.Put方法的原理
调用Put方法的时候发生了什么呢
比如调用 hashMap.put(apple, 0) 插入一个Key为“apple的元素。这时候我们需要利用一个哈希函数来确定Entry的插入位置index
index Hash“apple”
假定最后计算出的index是2那么结果如下但是因为HashMap的长度是有限的当插入的Entry越来越多时再完美的Hash函数也难免会出现index冲突的情况。比如下面这样这时候该怎么办呢我们可以利用链表来解决。
HashMap数组的每一个元素不止是一个Entry对象也是一个链表的头节点。每一个Entry对象通过Next指针指向它的下一个Entry节点。当新来的Entry映射到冲突的数组位置时只需要插入到对应的链表即可需要注意的是新来的Entry节点插入链表时使用的是“头插法”。至于为什么不插入链表尾部后面会有解释。2.Get方法的原理
使用Get方法根据Key来查找Value的时候发生了什么呢
首先会把输入的Key做一次Hash映射得到对应的index
index Hash“apple”
由于刚才所说的Hash冲突同一个位置有可能匹配到多个Entry这时候就需要顺着对应链表的头节点一个一个向下来查找。假设我们要查找的Key是“apple”第一步我们查看的是头节点Entry6Entry6的Key是banana显然不是我们要找的结果。
第二步我们查看的是Next节点Entry1Entry1的Key是apple正是我们要找的结果。
之所以把Entry6放在头节点是因为HashMap的发明者认为后插入的Entry被查找的可能性更大。————————————之前说过从Key映射到HashMap数组的对应位置会用到一个Hash函数
index Hash“apple”
如何实现一个尽量均匀分布的Hash函数呢我们通过利用Key的HashCode值来做某种运算。index HashCodeKey % Length ?如何进行位运算呢有如下的公式Length是HashMap的长度
index HashCodeKey Length - 1
下面我们以值为“book”的Key来演示整个过程
1.计算book的hashcode结果为十进制的3029737二进制的101110001110101110 1001。
2.假定HashMap长度是默认的16计算Length-1的结果为十进制的15二进制的1111。
3.把以上两个结果做与运算101110001110101110 1001 1111 1001十进制是9所以 index9。
可以说Hash算法最终得到的index结果完全取决于Key的Hashcode值的最后几位。假设HashMap的长度是10重复刚才的运算步骤单独看这个结果表面上并没有问题。我们再来尝试一个新的HashCode 1011100011101011101011 让我们再换一个HashCode 101110001110101110 1111 试试 是的虽然HashCode的倒数第二第三位从0变成了1但是运算的结果都是1001。也就是说当HashMap长度为10的时候有些index结果的出现几率会更大而有些index结果永远不会出现比如0111
这样显然不符合Hash算法均匀分布的原则。
反观长度16或者其他2的幂Length-1的值是所有二进制位全为1这种情况下index的结果等同于HashCode后几位的值。只要输入的HashCode本身分布均匀Hash算法的结果就是均匀的。—————END—————