为什么 hashmap 里 putMapEntries 只判断传入 map 的 size 是否大于当前 map 的阈值呢?
源码为 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.