根据源码可知,HashMap的get方法流程不是特别复杂,其中真正执行取值的逻辑是在getNode()方法中,不多说直接上源码。
这里再啰嗦一句:其中入参hash是调用了存值时的hash()方法,就是根据将key进行hash得到hash值,然后将hash值与Key进行异或操作(可以理解为加密),再进行无符号右移16位得到的。
/**
* Implements Map.get and related methods
*
* @param hash hash for key
* @param key the key
* @return the node, or null if none
*/
final Node<K,V> getNode(int hash, Object key) {
//tab为hashmap中存放链表的数组,first是链表表头
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
//判断链表数组是否为空,即当前hashmap是否为空,并且根据Key计算出数组下标,进而获取目标所在链表(或红黑树)的头结点
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
//判断链表头结点的值是否是所要获取的目标值,如果不是则不进入if
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;
}