putMapEntries函数会被HashMap的拷贝构造函数public HashMap(Map<? extends K, ? extends V> m)
或者LinkedHashMap类的构造函数public LinkedHashMap(Map<? extends K, ? extends V> m)
函数调用到
putMapEntries方法
/**
* 实现了 Map.putAll 和 Map 的构造
* 该函数用于将一个map赋值给新的HashMap
* @param m 传入map的集合
* @param evict 最初构建此映射时为false,否则为true
*/
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
// 获取传入map集合的大小
int s = m.size();
// 如果大小大于0
if (s > 0) {
// 判断"表"节点是否有初始化
if (table == null) { // pre-size
// 将map集合大小除以负载因子h后+1,可以得到HashMap所需的最大负载容量,也就是阈值
// 因为会计算出小数因此+1.0F向上取整
float ft = ((float)s / loadFactor) + 1.0F;
// 当不大于最大容器值的时候使用计算出来的ft的长度
// 否则如果大于,则使用的是最大容器的值
int t = ((ft < (float)MAXIMUM_CAPACITY) ?
(int)ft : MAXIMUM_CAPACITY);
// threshold 要调整大小的下一个大小值(容量*负载系数)
// 如果t大于当前最大负载容量,则进行调整
if (t > threshold)
// 返回给定目标容量的两个大小的幂
threshold = tableSizeFor(t);
}
//说明table已经初始化过了.判断传入map的size是否大于当前map的threshold,如果是,必须要resize
//这种情况属于预先扩大HashMap容量,再put元素
else if (s > threshold)
// 将表格大小初始化或加倍
resize();
// 将map中的元素逐一添加到HashMap中
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
K key = e.getKey();
V value = e.getValue();
putVal(hash(key), key, value, false, evict);
}
}
}
【注】
float ft = ((float)s / loadFactor) + 1.0F
这里的加1是因为,size / loadFactor = capacity,但如果算出来的capacity是小数,却又向下取整,会造成容量不够大,所以,如果是小数的capacity,那么必须向上取整- 计算出来的容量必须小于最大容量
MAXIMUM_CAPACITY
,否则直接让capacity等于MAXIMUM_CAPACITY
if (t > threshold)
这里的threshold成员实际存放的值是capacity的值。因为在table还没有初始化时(table还是null),用户给定的capacity会暂存到threshold成员上去(毕竟HashMap没有一个成员叫做capacity,capacity是作为table数组的大小而隐式存在的)else if (s > threshold)
说明传入map的size都已经大于当前map的threshold了,即当前map肯定是装不下两个map的并集的,所以这里必须要执行**resize()**操作putval
也是使用的默认修饰符,因此只能被本类或者该包下的类访问到,最后循环里的putVal
可能也会触发resize操作