HashMap的get()源码
public V get(Object key) {
//定义一个Node对象来接收
Node<K,V> e;
//调用getNode()方法,返回值赋值给e,如果取得的值为null,就返回null,否则就返回Node对象e的value值
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
//取hash值方法,HashMap的put方法的也是调用了这个方法,get方法也调用这个方法,保证存取时key值对应的hash值是一致的,这样才能正确对应
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
final Node<K,V> getNode(int hash, Object key) {
//定义几个变量
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
//首先是判断数组table不能为空且长度要大于0,同时把数组长度tab.length赋值给n
if ((tab = table) != null && (n = tab.length) > 0 &&
//其次是通过[(n - 1) & hash]获取key对应的索引,同时数组中的这个索引要有值,然后赋值给first变量
(first = tab[(n - 1) & hash]) != null) {
//这个first其实就是链表头的节点了,接下来判断first的hash值是否等于传进来key的hash值
if (first.hash == hash &&
//再判断first的key值赋值给k变量,然后判断其是否等于key值,或者判断key不为null时,key和k变量的equals比较结果是否相等
((k = first.key) == key || (key != null && key.equals(k))))
//如果满足上述条件的话,说明要找的就是first节点,直接返回
return first;
//走到这步,就说明要找的节点不是首节点,那就用first.next找它的后继节点 ,并赋值给e变量,在这个变量不为空时
if ((e = first.next) != null) {
//如果首节点是树类型的,那么直接调用getTreeNode()方法去树里找
if (first instanceof TreeNode)
//这里就不跟进去了,获取树中对应key的节点后直接返回
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
//走到这步说明结构还是链表
do {
//这一步其实就是在链表中遍历节点,找到和传进来key相符合的节点,然后返回
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
//获取e节点的后继节点,然后赋值给e,不为空则进入循环体
} while ((e = e.next) != null);
}
}
//以上条件都不满足,说明没有该key对应的数据节点,返回null
return null;
}