源码为 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 的二倍了。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.