1.HashMap 的类继承关系

图示即为 Map 相关类的继承关系。源码中的类签名如下:
public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {......
}
2.HashMap 的底层存储结构
HashMap 的底层存储结构是 Node 类, 实现了 Map 中的 Entry。即 HashMap 底层是由 Node 数组实现存储的。
3.JDK 1.8 中 HashMap 中重要的几个知识点
3.1 数组容量始终为 2 的 N 次幂
HashMap 的数组容量始终为 2 的 N 次幂。原因是当数组容量为 2 的 N 次幂时, hash() 方法计算出来的 hash 值直接与(数组容量 - 1) 进行 & (位与)运算就可以得到元素在数组中的下标。
3.2 链表与红黑树的相互转化条件
- 链表转红黑树: 链表长度大于等于 8, 且数组的长度大于64。注意, 链表长度大于等于8一个条件并不会把链表转化为红黑树, 只有两个条件都满足才会触发链表转红黑树的操作, 否则会触发一次resize()。
- 红黑树转链表: 红黑树的节点小于等于 6时。
4.HashMap 在 JDK 1.7 中的死锁问题
HashMap 在 JDK 1.7 版本中, 在并发写入的情况下可能会出现死锁的问题。这主要是因为链表的插入方式采用的是头插法。
5.JDK 1.8 进行的优化
- 数组+链表改成了数组+链表or红黑树
- 链表的插入方式从头插法变成了尾插法
- 扩容与插入顺序的变化: JDK 1.7中, 先判断是否需要扩容再插入,JDK 1.8中, 先插入再判断是否需要扩容
- 扩容时重新定位元素位置的方法不同
 -JDK 1.7中, 需要调用hashcode方法来重新定位在新数组的位置
 -JDK 1.8中, 直接使用了JDK 1.7中的规律, 即扩容后新数组中的位置 = 原位置or原位置+旧容量