前言
之前周会技术分享,一位同事讲解了HashMap的源码,涉及到一些常量设计的目的,本文将谈谈这些常量为何这样设计,希望大家有所收获。
HashMap默认初始化大小为什么是1 << 4(16)
/**
* The default initial capacity - MUST be a power of two.
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
HashMap默认初始化大小为什么是16,这里分两个维度分析,为什么是2的幂,为什么是16而不是8或者32。
默认初始化大小为什么定义为2的幂?
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;
if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash,
key, value, null);
我们知道HashMap的底层数据结构是数组+链表/数组+红黑树,由以上方法,可以发现数组下标索引的定位公式是:i = (n - 1) & hash,当初始化大小n是2的倍数时,(n - 1) & hash等价于n%hash。定位下标一般用取余法,为什么这里不用取余呢?
因为,与运算(&)比取余(%)运算效率高
求余运算: a % b就相当与a-(a / b)*b 的运算。
与运算: 一个指令就搞定
因此,默认初始化大定义为2的幂,就是为了使用更高效的与运算。
默认初始化大小为什么是16而不是8或者32?
如果太小,4或者8,扩容比较频繁;如果太大,32或者64甚至太大,又占用内存空间。
打个比喻,假设你开了个情侣咖啡厅