源码为 jdk1.8.
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
int s = m.size();
if (s > 0) {
if (table == null) { // pre-size
float ft = ((float)s / loadFactor) + 1.0F;
int t = ((ft < (float)MAXIMUM_CAPACITY) ?
(int)ft : MAXIMUM_CAPACITY);
if (t > threshold)
threshold = tableSizeFor(t);
}
//说明 table 已经初始化过了,直接判断 s 是否大于当前 map 的阈值
else if (s > threshold)
resize();
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);
}
}
}
但是else if (s > threshold)这里为什么不直接写成else if ((s + size) > threshold)呢?难道不应该把传入 map 的映射数量和当前 map 的映射数量加起来再比吗?
这样的话,可能在最后的循环里的某个 putVal 里,又会再次 resize 啊。
还有一个问题就是,为什么 float ft = ((float)s / loadFactor) + 1.0F;最后还要加 1 啊? 就是因为这个加 1,导致下面这段代码:
import java.util.*;
public class test1 {
public static void main(String[] args) {
HashMap<String,Integer> oldMap = new HashMap<String,Integer>();
for(int i=0;i<12;i++){
oldMap.put(""+i,i);
}
HashMap<String,Integer> newMap = new HashMap<String,Integer>(oldMap);
System.out.println();
}
}
里面的 newMap 明明和 oldMap 的映射数量一样,但是其容量和阈值都是 oldMap 的二倍了。
可见 oldMap 的容量是 16,阈值是 12.但 newMap 的容量是 32,阈值是 24.
因为 12/0.75=16,16 再加=17,17 再 tableSizeFor 得到 32.