回顾一下上一篇文章,介绍的是put 相关函数。了解了HashMap put的过程,何时扩容以及何时将链表转为红黑树。接下来将介绍HashMap get相关函数以及常见的面试题。java
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
/** * 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) {
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) {//注释1
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))//注释2
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)//注释3
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {//注释4
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
复制代码
能够看到get(Object key) 函数的主要逻辑是在getNode(int hash, Object key)中,相对而言逻辑是比较简单的。node
HashMap 的数据结构?
哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优势。当链表长度超过 8 时,链表转换为红黑树。面试
HashMap的底层原理是什么?
基于hashing的原理,jdk8后采用数组+链表+红黑树的数据结构。咱们经过put和get存储和获取对象。当咱们给put()方法传递键和值时,先对键作一个hashCode()的计算来获得它在bucket数组中的位置来存储Entry对象。当获取对象时,经过get获取到bucket的位置,再经过键对象的equals()方法找到正确的键值对,而后在返回值对象。数组
HashMap 的底层数组长度为什么老是2的n次方
HashMap根据用户传入的初始化容量,利用无符号右移和按位或运算等方式计算出第一个大于该数的2的幂。使数据分布均匀,减小碰撞当length为2的n次方时,h&(length - 1) 就至关于对length取模,并且在速度、效率上比直接取模要快得多。markdown
hash 碰撞的处理 (如下问题留给读者)数据结构
HashMap 扩容机制函数
HashMap和Hashtable的区别spa