- 问题一:HashMap 初始化分配内存了吗?
- 问题二:HashMap 什么时候分配的内存?第一次分配了多少?
- 问题三:什么时候触发
rehash
? - 问题四:
loadFactor
有什么作用?
环境
╰─$ java -version 255 ↵
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
源码解答
问题一
构造函数里没有分配底层存储,只是计算了阈值
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
loadFactor
默认 0.75
实测 tableSizeFor(100) = 128
tableSizeFor(1000) = 1024
tableSizeFor(4097)=8192
问题二
在第一次 put
的时候检查table == null
,调用 resize()
分配内存, 源码中第 628 行
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
第一次初始化的容量赋值在 694 行
newCap = DEFAULT_INITIAL_CAPACITY; //16
实际分配在 704
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
问题三
put(k, v)
的最后会检查阈值,如果超过 threshold
就进行 resize()
, 662 行
if (++size > threshold)
resize();
在第 687 行赋值新容量, 扩大一倍,容量值最大不会超过 2 的 30 次方
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // double threshold
接着就是 rehash
的详细过程~
问题四
先看变量定义, 这是一个 final 变量, 初始化后就不会变了
/**
* The load factor for the hash table.
*
* @serial
*/
final float loadFactor;
第一个找到的地方在 putMapEntries
方法里, 第 504 行
float ft = ((float)s / loadFactor) + 1.0F;
s
变量是 putMapEntries
方法参数 Map<? extends K, ? extends V> m
的 size()
,
![](https://img.haomeiwen.com/i4887447/950268064cf63ad3.png)
四个地方被调用,差不多都是
putAll
的作用
刷新阈值 threshold
, 看完理解下来意思是新 map
的 size()
除以 loadFactor
再加 1 , 如果比 threshold
大就更新 threshold
,加大后的值是一个 2 的 n 次方
第二次使用的地方在 698 行
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
作用依然是刷新阈值, 新阈值 threshold
等于 新容量 newCap
乘以 loadFactor
, 阈值起作用的地方参看问题三
网友评论