HashMap的构造方法
//默认负载因子值
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//HashMap最大容量:2的30次方
static final int MAXIMUM_CAPACITY = 1 << 30;
//当前HashMap所能容纳的键值对的最大值,超过就会进行扩容
int threshold;
//负载因子
final float loadFactor;
//构造方法一,常用的构造方法,调用会把负载因子设置为默认值0.75
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
//构造方法二,这里会传入一个初始容量值,然后调用构造方法三
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
//构造方法三
public HashMap(int initialCapacity, float loadFactor) {
//如果初始容量设置成小于0,则抛出IllegalArgumentException异常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
//如果设置的初始值比默认的最大容量值还大
if (initialCapacity > MAXIMUM_CAPACITY)
//就强行赋值成默认的最大容量值:2的30次方
initialCapacity = MAXIMUM_CAPACITY;
//判断loadFactor变量值的合法性,不符合要求则抛出IllegalArgumentException异常
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
//赋值loadFactor
this.loadFactor = loadFactor;
//返回一个个大于或等于initialCapacity的最小2的幂值,并赋值
this.threshold = tableSizeFor(initialCapacity);
}
//构造方法四,入参是一个Map类型
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
//将传入参数m的所有元素存入本HashMap对象实例中
putMapEntries(m, false);
}
//这个方法就是为了返回一个大于或等于cap的最小2的幂值,比如cap=15,就返回16,如果cap=17,就返回32
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
//将传入参数m的所有元素存入本HashMap对象实例中的操作
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
//获取m的长度
int s = m.size();
//如果长度大于0,说明m里有元素,则将m里的元素放入到本HashMap对象实例中
if (s > 0) {
//如果table是null,说明本HashMap对象实例里还没任何元素,因为table值的初始化是在HashMap做put操作时
if (table == null) {
//得出了本HashMap要存在m中的元素所需的最小容量,这里加一是怕算出小数,所以向上取整
float ft = ((float)s / loadFactor) + 1.0F;
//对最小容量ft做判断,小于最大容量则赋值ft值给t,否则就取最大容量值2的30次方
int t = ((ft < (float)MAXIMUM_CAPACITY) ?
(int)ft : MAXIMUM_CAPACITY);
//如果容量t的值比threshold大
if (t > threshold)
//找出比t大的最小2次幂值,赋值给threshold,作为本HashMap的容量
threshold = tableSizeFor(t);
}
//如果table不等于null,说明里面已经有元素了,那就要判断m集合里的元素个数是否大于threshold,超过了就要进行扩容
else if (s > threshold)
//扩容方法
resize();
//遍历m集合,存放进本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);
}
}
}