一、HashMap的四个构造函数:
1、
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);
}
2、
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
3、
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
4、
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);
}
二、构造函数解释:
- 前三个构造函数可以统一看,从源码中可以看出,使用构造函数创建HashMap时,只是把HashMap的加载因子进行初始化,如果指定了初始化容量大小则把容量也初始化。可以看到,构造函数只是赋值了容量、阈值和加载因子这三个属性,并没有对存储数据的table数组进行赋值,什么时候赋值呢?答案是第一次put数据的时候。下一节说。
构造函数里面还有一个tableSizeFor方法,此方法的作用就是算出比输入的数大且最接近2的整数幂的数。原理简单说一下:
一个二进制的数,先无符号右移一位再和原来的数进行位或操作,就会把原来最高位的1后面的一个数也变成1,这样就有两个1了。同理,再右移两位,就有四个1了,以此类推,先右移1位,然后再位移2位,再位移4位,再位移8位,最后就会得到一个全是1的二级制数,最后再加一就是最大的2次幂了。举个栗子:
原来数为 0111 1100 0011 1101
右移一位 0011 1110 0001 1110
再位或得 0111 1110 0011 1111
右移两位 0001 1111 1000 1111
再位或得 0111 1111 1011 1111
。。。。。
以此类推发现为1的最高位后面在渐渐补1,最后都补满1再加1也就是最接近的2次幂了。所以对于int来说,本身占用32个二进制位,只需要位移1,2,4,8,16即可。
- 对于最后一个构造函数,就是构造时再传入一个HashMap,个人理解有点像为了达到类似clone的功能,再复制一个和原来不同引用的HashMap,以满足使用。putMapEntries方法也是判断是否需要扩容重新指定阈值一系列操作,然后遍历那个HashMap中的值再放入到新的HashMap中。