# HashMap实现原理

HashMap是常考点，而一般不问List的几个实现类(偏简单)。以下基于JDK1.8.0_102分析。

JDK版本：oracle java 1.8.0_102

# 内部存储

HashMap的内部存储是一个数组（bucket），数组的元素Node实现了是Map.Entry接口(hash, key, value, next)，next非空时指向定位相同的另一个Entry，如图：

image.png

Tips:

• 如果数据增长很快的话，或数据规模可预知，可以在创建HashMap时主动设置capacity

# hash与定位

``````static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
``````

## hash方法的实现和定位

image.png

Computes key.hashCode() and spreads (XORs) higher bits of hash to lower. Because the table uses power-of-two masking, sets of hashes that vary only in bits above the current mask will always collide. (Among known examples are sets of Float keys holding consecutive whole numbers in small tables.) So we apply a transform that spreads the impact of higher bits downward. There is a tradeoff between speed, utility, and quality of bit-spreading. Because many common sets of hashes are already reasonably distributed (so don’t benefit from spreading), and because we use trees to handle large sets of collisions in bins, we just XOR some shifted bits in the cheapest possible way to reduce systematic lossage, as well as to incorporate impact of the highest bits that would otherwise never be used in index calculations because of table bounds.

``````(n - 1) & hash
``````

## 碰撞

``````    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;
}
``````

• 覆写后，一定要保证equals判断相等的时候，hashCode的返回值也相等
• 对于选作key的类，要保证调用put与get时hashCode的返回值相等，equals的性质相同

# resize

resize是HashMap中最难理解的部分

Initializes or doubles table size. If null, allocates in accord with initial capacity target held in field threshold. Otherwise, because we are using power-of-two expansion, the elements from each bin must either stay at same index, or move with a power of two offset in the new table.

image.png

image.png

image.png

### 推荐阅读更多精彩内容

• 本篇所述源码基于JDK1.8.0_121 在写上一篇线性表的文章的时候，笔者看的是Android源码中suppor...
Geeks_Liu阅读 9,267评论 2 40
• 1. HashMap的数据结构 在java编程语言中，最基本的结构就是两种，一个是数组，另外一个是模拟指针（引用）...
爱码士平头哥阅读 165评论 0 0
• HashMap 是 Java 面试必考的知识点，面试官从这个小知识点就可以了解我们对 Java 基础的掌握程度。网...
野狗子嗷嗷嗷阅读 5,804评论 9 108
• Hash算法 Hash，一般翻译做“散列”，也直接音译为“哈希”。就是把任意长度的输入通过散列算法，变换成固定长度...
Josaber阅读 1,743评论 6 72
• 转眼间就是国庆了。时间果然就像细沙一样，谁也没办法握住。记得去年的这个时候我还在学校的宿舍里面安逸的看着书、搞着娱...
阿历克斯奇阅读 62评论 0 0