跟我一起阅读Java源代码之HashMap(二)
上一节中实现的SimpleHashMap,没有解决冲突的问题,这一节我们继续深入
由于table的大小是有限的,而key的集合范围是无限大的,所以寄希望于hashcode散落,肯定会出现多个key散落在同一个数组下标下面,
因此我们要引入另外一个概念,将key和value同时存入table[index]中,即将key和value构成一个对象放在table[index],而且可能存放多个,他们的key对应的index相同,但是key本身不同
现在我们就该讨论以什么样的方式存储这些散落在同一个数组下标的元素
可以考虑数组?
也可以考虑链表存储
源码里面是用链表存储的,其实我也没明白这两种方式在这里有什么区别
,感觉无论在检索和存储上都是差不多的效率,
检索都是需要遍历的方式,而存储也可以是顺序的
那这个问题留给大家吧。
我们来实现链式存储的方式,首先定义一个链表数据结构Entry:
public class Entry<K, V> { //存储key final K key; //存储value V value; //存储指向下一个节点的指针 Entry<K, V> next; //存储key映射的hash final int hash; }
新的EntryHashMap实现方式
public class EntryHashMap<K, V> { transient Entry[] table; transient int size; public V put(K key, V value) { //计算出新的hash int hash = hash(key.hashCode()); //计算出数组小标i int i = indexFor(hash, table.length); //遍历table[i],如果table[i]没有与新加入的key相等的,则新加入 //一个value到table[i]中的entry,否则将新的value覆盖旧的value并返回旧的value for (Entry<K, V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; return oldValue; } } addEntry(hash, key, value, i); return null; } public void addEntry(int hash, K key, V value, int bucketIndex) { Entry<K, V> e = table[bucketIndex]; //将新的元素插入链表前端 table[bucketIndex] = new Entry<>(hash, key, value, e); size++; } /** * 通过hash code 和table的length得到对应的数组下标 * * @param h * @param length * @return */ static int indexFor(int h, int length) { return h & (length - 1); } /** * 通过一定算法计算出新的hash值 * * @param h * @return */ static int hash(int h) { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } }
作者:风过无痕-唐
出处:http://www.cnblogs.com/tangyanbo/
本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。 如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步! 再次感谢您耐心的读完本篇文章。欢迎加QQ讨论群
出处:http://www.cnblogs.com/tangyanbo/
本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。 如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步! 再次感谢您耐心的读完本篇文章。欢迎加QQ讨论群
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?