Java之HashMap源码分析(第五篇:访问元素)
(注意:本文源码基于JDK1.8)
两个get()方法,均可以获取Value对象,我们一起学习一下
get(Object)方法分析
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
用于返回指定Key对象对应的Value元素,Value对象即为元素,传入的参数key表示Key对象
1、定义一个局部变量e,它的类型是Node,用于持有返回的结点对象
2、获取Key对象对应的hash值
先调用静态方法hash(),目的是为了得到将Key对象经过二次扰动后的值,称为hash值
3、获取指定Key对象对应的Node对象
调用getNode()方法,将静态方法hash()返回的值与Key对象同时传入了进去,getNode()方法的返回值会赋值给局部变量e
4、判断是否获取到Node对象,并返回给调用方结果
对局部变量e进行判断,为null,说明没有找到Key对象对应的Node对象,此时返回null
如果获取到Node对象,则取出Node对象持有的value,并返回给调用方,此value为元素对象
getNode()方法分析
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
用于根据hash值与Key对象,返回对应的Node对象的方法,传入的参数hash表示Key对象的hash值(二次扰动后的值),传入的参数key表示Key对象
1、创建几个局部变量,用于存储过程值
局部变量tab用于存储HashMap对象持有的底层数组对象
局部变量first用于存储数组桶中的第一个Node对象
局部变量e用于存储单链表遍历过程中的每个Node对象
局部变量n用于存储底层数组对象的容量
局部变量k用于存储Key对象
2、先做三个判断
判断旧数组table是否已经创建
判断旧数组table是否已经长度大于0
判断旧数组某个下标处是否包含有元素(桶地址的计算:通过数组的长度与Key对象经过二次扰动后的hash值进行位与运算而得出)
3、针对下标处的三种情况分别处理
对下标处(桶地址)只有一个元素进行处理:先取出Node对象持有的hash值进行比较,相等的情况下,继续通过Node对象持有的key对象与传入的key对象进行==的比较,如果==是不相等的情况,继续通过key对象的equals()方法进行比较(这是为了照顾Key对象为null的情况,作者写的很巧妙)
对下标处(桶地址)为单链表的情况进行处理:对单链表进行遍历,直到找到匹配的情况
对下标处(桶地址)为红黑树的情况进行处理:当桶中的对象为TreeNode说明为红黑树结构,通过另外一个getTreeNode()方法进行比较
4、上面的三种情况,只要一种符合元素的要求,返回Node对象,否则返回一个null,表示没有匹配的对象
静态方法hash()分析
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
用于根据Key对象再重新计算出一个hash值的方法,在前文中已经做了分析,此处不再做分析
getOrDefault()方法分析
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;
}
用于获取Value对象的方法,特点是可以指定一个参数defaultValue,当通过Key找不到对应Value时,会返回指定的默认值
总结
1、HashMap的添加、删除、访问元素,均有静态方法hash()的参与,可见这个静态方法是多么重要
本文地址:https://blog.csdn.net/cadi2011/article/details/104729092
推荐阅读
-
Java之HashMap源码分析(第五篇:访问元素)
-
Java之LinkedList源码分析(第三篇:添加元素-List接口)
-
Java基础之Collections框架Map接口实现类HashMap及其源码分析(1)
-
Java容器之HashMap源码分析(妈妈再也不用担心我不懂HashMap了)
-
Java集合系列之HashMap源码分析
-
Java之LinkedList源码分析(第三篇:添加元素-List接口)
-
Java基础之Collections框架Map接口实现类HashMap及其源码分析(1)
-
Java之LinkedList源码分析(第五篇:结点类)
-
Java之HashSet源码分析(第三篇:访问)
-
Java之HashMap源码分析(第五篇:访问元素)