| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> HashMap的理解 -> 正文阅读 |
|
[数据结构与算法]HashMap的理解 |
底层数据结构HashMap底层是哈希表(hash table,也叫作散列表),为了解决哈希碰撞,又在原来的基础上把每个数组的元素扩展成一个个链表。简单理解的话,结构=数组(也叫作哈希桶)+链表,注意的是在jdk8以后,为了更高效的查询,在满足一定条件下,将链表转化成红黑树。 hash()方法
key.hashCode()是底层的一个函数,说实话我也不了解其实现原理。我只知道他会返回一个32位的2进制数。当得到32位的数据后,下一步的操作是把此数据和自身的高16位进行异或操作。 为什么要和自身的高16位异或?我们再得到key之后,是想把这个key的值转成数组中的下标,以驻足长度为16进行距离。如果我们得到一个hashcode的返回值1111 0000 1111 0000 1111 0000 1111 0000,直接人为他是hash值,接下来他会和(n-1)15(1111)进行&操作,得到低四位0000。如果另一个数据是1111 1100 1111 0110 1111 0110 1111 0000,经过上述的操作,低四位也是0000。意味着这两个数据会放在同一个下标处。没有达到我们的预期:让数据分散开。 而与高16位异或的步骤如下:
接下来第一个hash值和1111相与,得到0000(下标0)。第二个hash值和1111与操作,得到0110(下标6)。所以此时两个数据分离开了。 和高16位异或可以数据分布不均匀,这样可以保证高位的数据也参与到与运算中来,以增大索引的散列程度[1]。 &操作是二者都为1时,结果等于1,所有大多数情况下结果为0,即此操作会让结果更趋近于0。|操作是二者有一个1时,结果就为1,所以结果会更趋近1。异或可以保证两个数值的特性,不至于趋近0或1。 putVal()方法
以上在参考相关博客后,我写出来自己的理解[2,3]。对于红黑树,可能需要在学习。 总结:先调用hashcode()方法得到hash值,然后通过哈希算法得到数组的下标值。如果这个位置上什么都没有,返回null。如果这个位置上有链表,拿着k与链表上Node的k进行equals比较,如果返回true,则这个节点就是我们要得到的,更新数据,如果结果全是false,把数据添加到链表最后。 为什么每次扩容2倍?我们在得到下标时,是进行(n-1)&hash的操作。最开始是1111和hash值进行&操作。首先这个结果必然在0-15,不会超过数组下标。扩容后,我们是不是想让5个1和hash&操作,此时11111-->31,所以n=32,再次扩容后6个1和hash&操作,此时111111->63,所以n=64。其实每加一个1,数据就扩大2倍。所以扩容2倍。 为什么数组长度最大值是2^30?
所以当1不断左移时,数组长度不断变大,对应的n-1中的全1位也在变多。由上面的规律可知,1最多到第32位,所以此时是2^31。但是int数据类型的最高位是符号位,所以1不能左移过去,所以最终长度为2^30. 键值对都可以为nullkey为null时,hash = 0。 if ((p = tab[i = (n - 1) & hash]) == null)? tab[i] = newNode(hash, key, value, null); 此时tab[0] == null,所以可以插入值。 理解为什么map中的k是无序且不可重复? 参考: [1]:为什么HashMap使用高16位异或低16位计算Hash值? - 知乎 (zhihu.com) [2]:HashMap(一)——HashMap put方法原理_自恃无情的博客-CSDN博客_hashmap的put方法实现原理 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 21:49:17- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |