| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 深度分析HashMap的put方法源码 -> 正文阅读 |
|
[数据结构与算法]深度分析HashMap的put方法源码 |
它还会有一个哈希运算,就是为了避免哈希冲突。何为哈希冲突?不同的key值(也就是说是不同的对象),最终得到的hash值是相同的。造成锁定到同一个索引位置?。 ? ?这里key即是我们传进来的new A(i),通过运行时绑定,可知调用的hashCode方法就是我们重写的 因为A这个类默认是继承Object这个类的。 hashCode方法是属于Object这个java类的,但是当子类重写了这个方法之后,我们每当调用这个方法,编译的时候看父类是否有这个方法,来决定是否编译的时候会报错。 然而运行的时候,是先从子类开始找这个hashCode方法,子类如果有,那么就使用子类的hashCode方法,如果子类没有,那么一层层的往父类,爷类进行寻找这个hashCode方法 ? ? 接下来分析一下这个put底层的putVal方法 底层先维护了一个静态内部类,原来维护Node<K,V>节点。 在putVal添加的过程中我们,维护了一个Node<K,V>[ ]? tab;数组,数组中将来放的每一个元素的类型就是Node<K,V>类型, 为了把传进来的key,value值封装为一个Node<K,V>节点对象存储在底层维护的ode<K,V>[ ]? tab数组中 ?开始分析: ?如果一开始这个节点数组为空,那么我们就要进行扩容操作。 ?当这个节点数组不为空之后,我们就可以通过计算算出该key对应的索引位置,hash值是通过key对象计算得来的。。。底层也会有一层计算索引的运算法则,如下图: 如果该位置没有节点,那么就直接插入 ??如果该位置有节点, 我们就要判断该位置已插入的节点和我们待插入的节点是否是相同的。。 如何判断它俩是否是相同的呢? 我们需要满足两个条件: 1.首先hash值必须相同。已插入Node<K,V>节点对象的hash属性值和传进来的hash值相等 2.接下来就要判断已插入Node<K,V>节点对象的key属性值和传进来的key是否相同,类型为泛型。如果相同,那么就说明第二个条件成立。 如果说发现不相同,没关系,对于第二个条件,我们还有一个选择,满足就可以说明已插入的节点和待封装插入的是相同的,也就是key.equals(k)。 这个equals方法是Object类的方法 但是只要我们key对象所对应的类中重写这个equals方法,我们就会优先调用子类中重写父类Object的equals方法【运行时绑定】。所以说,这个equals比较规则可以由我们自己决定。 ok,如果说该equals方法返回true,那么就可以证明出是相同的啦!! --但是记住,一切的前提就是先满足第一个条件!! 那么就会记录这个p,p在前面确定索引位置的时候已经赋过值了,见上一个图 --------------- 小结: 我们知道hash值相同,不一定说明这俩就是同一个对象 但是同一个对象,所求出的hash值肯定是相同的。 所以说,当我们判断出hash值相等的时候,并不能百分比确定它俩就是同一个key对象,不能断定然后直接记录之后value值覆盖 所以说,我们要满足两个条件, 1.已插入Node<K,V>节点对象的hash属性值和传进来的hash值相等 2.已插入Node<K,V>节点对象的key属性值和传进来的key相同? ?或? 当key不为空时,key通过equals方法返回true【第二个条件中满足一个就说明第二个条件成立!!!这是 "||"关系,如果前面的一个满足,后面就不用再看了。】 ----------------- 接下来继续 ?当发现待插入的key对象和该索引位置第一个节点对象不是同一个key对象的时候,我们就要进行情况判断,该索引位置处的节点成树状,那么就要进行树状式添加。 ?如果是链条形式: ?那么就要先遍历整个链条, 依次进行比较已插入的节点对象的hash属性和待封装为Node<K,V>节点并插入 比较规则同上 在遍历的过程中, 如果发现下一个索引位置处为null,那么直接封装传进来的key value hash 值封装为一个Node<K,V>类型的节点。 ?但是当tab这个我们底层维护的数组的长度大于64,并且该链条长度大于等于8时,我们就要进行树化操作。目的就是为了提高查找性能,优化效率! ? ?OK,结束! |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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/26 13:25:16- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |