HashMap 源码
属性
默认长度
如不传入初始化长度,则默认长度为 16
/** * The default initial capacity - MUST be a power of two. */static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
阈值
所能包容的 key-value 对的极限,超过此值就须要进行扩容
/** * The next size value at which to resize (capacity * load factor).*/int threshold;
底层数组
HashMap 底层寄存 Node 节点的数组,在第一次应用的时候进行初始化,长度总为 2 的 N 次幂
HashMap 保障扩容后长度 n 总为 2 次方是因为计算 Node 所在索引时采纳了 (n - 1) & hash
运算进行优化(& 比 % 效率更高),等价于对 n 取模,也就是 h % n
/** * The table, initialized on first use, and resized as * necessary. When allocated, length is always a power of two. * (We also tolerate length zero in some operations to allow * bootstrapping mechanics that are currently not needed.) */transient Node<K,V>[] table;
负载因子
如不传入负载因子,默认为 0.75
负载因子过大会导致空间利用率较低,过小会导致碰撞概率变大,查问效率变低
/** * The load factor used when none specified in constructor. */static final float DEFAULT_LOAD_FACTOR = 0.75f;
扩容为树的阈值
当链表长度大于 8 时,会转变为红黑树
/** * The bin count threshold for using a tree rather than list for a * bin. Bins are converted to trees when adding an element to a * bin with at least this many nodes. The value must be greater * than 2 and should be at least 8 to mesh with assumptions in * tree removal about conversion back to plain bins upon * shrinkage. */static final int TREEIFY_THRESHOLD = 8;
回退为链表的阈值
当树中节点少于 6 个时,会转变为链表
/** * The bin count threshold for untreeifying a (split) bin during a * resize operation. Should be less than TREEIFY_THRESHOLD, and at * most 6 to mesh with shrinkage detection under removal. */static final int UNTREEIFY_THRESHOLD = 6;
能够树化的最小底层数组长度
如果底层数组长度小于 64 时,阐明底层元素并不多,只是调配到某个地位的元素较多,先不转变为红黑树,先扩容底层数组扩散开
/** * The smallest table capacity for which bins may be treeified. * (Otherwise the table is resized if too many nodes in a bin.) * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts * between resizing and treeification thresholds. */static final int MIN_TREEIFY_CAPACITY = 64;
在 treeifyBin(Node<K,V>[] tab, int hash)
办法中,如果当先底层数组长度小于 MIN_TREEIFY_CAPACITY
会进行扩容
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) resize();
重要办法
hash 算法
采纳 hashCode()
的高 16 位异或低 16 位实现,能够保障高下 16 位都会参加到运算中
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}
put 流程
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; // 第一次应用,底层数组还没有初始化,进行初始化 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; // n 为底层数组长度,(n - 1) & hash 后果为[0,n-1] // 如果为 null 则此处不存在任何 Node,间接新建 Node 放到此处即可 // HashMap 保障扩容后长度 n 总为 2 次方,因为 & 比 % 具备更高的效率 // 所以采纳了 (n - 1) & hash 运算进行优化,等价于对 n 取模,也就是 h % n if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k; // 判断 Key 是否曾经存在,如果 key 存在,间接解决抵触 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; // 曾经转化为红黑树了 else if (p instanceof TreeNode) // 把节点插入到红黑树中 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { // 仍是链表,采纳拉链法解决抵触 for (int binCount = 0; ; ++binCount) { // 遍历到了链表尾部,阐明链表中 key 不存在抵触 if ((e = p.next) == null) { // 把新的 Node 插入到链表尾部 p.next = newNode(hash, key, value, null); // 在链表尾部新插入了一个 Node,此时链表长度为 binCount + 1 // 相当于:链表长度 (binCount + 1) >= TREEIFY_THRESHOLD if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st // 转变为红黑树 treeifyBin(tab, hash); break; } // 链表内有存在 Key,跳出循环,解决抵触 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } // 解决 key 抵触的状况 if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) // 把抵触的 Node 的 value 替换掉 e.value = value; afterNodeAccess(e); // 返回被替换的 Node 的 value return oldValue; } } ++modCount; // 超过能包容 KV对的阈值,进行扩容 if (++size > threshold) resize(); afterNodeInsertion(evict); return null;}
扩容办法
final Node<K,V>[] resize() { Node<K,V>[] oldTab = table; int oldCap = (oldTab == null) ? 0 : oldTab.length; int oldThr = threshold; int newCap, newThr = 0; if (oldCap > 0) { // 超过最大值,不再进行扩容,此时会产生大量碰撞 if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return oldTab; } // 扩容为原来的两倍 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) newThr = oldThr << 1; // double threshold } else if (oldThr > 0) // initial capacity was placed in threshold newCap = oldThr; else { // zero initial threshold signifies using defaults newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); } // 计算新的 KV 对阈值 if (newThr == 0) { float ft = (float)newCap * loadFactor; newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE); } threshold = newThr; @SuppressWarnings({"rawtypes","unchecked"}) Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; table = newTab; if (oldTab != null) { // 从新计算索引,放入到新表中 for (int j = 0; j < oldCap; ++j) { Node<K,V> e; if ((e = oldTab[j]) != null) { oldTab[j] = null; if (e.next == null) newTab[e.hash & (newCap - 1)] = e; else if (e instanceof TreeNode) ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); else { // preserve order Node<K,V> loHead = null, loTail = null; Node<K,V> hiHead = null, hiTail = null; Node<K,V> next; do { next = e.next; if ((e.hash & oldCap) == 0) { if (loTail == null) loHead = e; else loTail.next = e; loTail = e; } else { if (hiTail == null) hiHead = e; else hiTail.next = e; hiTail = e; } } while ((e = next) != null); if (loTail != null) { loTail.next = null; newTab[j] = loHead; } if (hiTail != null) { hiTail.next = null; newTab[j + oldCap] = hiHead; } } } } } return newTab;}