最近看HashMap中的源码,发现了一个精巧的代码,就是初始容量大小的设定
这里是基于JDK 1.8的HashMap,观察一下源码,发现HashMap一共有三个构造器
-
第1个构造器是两个参数,一个是初始大小initialCapacity,一个是装载因子loadFactor,
-
第2个构造器是一个参数,初始大小initialCapacity,调用构造方法1,装载因子为0.75
-
第3个构造器没有参数,构造容量为16,装载因子为0.75
首先我们讨论一下装载因子loadFactor,这个值的设定是让我们知道HashMap是否需要扩容用的。HashMap有一个确定容量,还有一个属性表示的是HashMap中目前装入了多少数据,如果装入的数据量超过确定容量*装载因子时,HashMap就需要扩容了。例如,当前容量是32,装载因子为0.75,当装入数据量达到24时,HashMap就要进行扩容了。
/**
* Constructs an empty <tt>HashMap</tt> with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
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);
}
/**
* Constructs an empty <tt>HashMap</tt> with the specified initial
* capacity and the default load factor (0.75).
*
* @param initialCapacity the initial capacity.
* @throws IllegalArgumentException if the initial capacity is negative.
*/
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
/**
* Constructs an empty <tt>HashMap</tt> with the default initial capacity
* (16) and the default load factor (0.75).
*/
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
我主要想说一下的是这里的tableSizeFor(int cap) ,这是一个巧妙的代码,直接就得到大于等于当前数的最小2的幂,就是当前数变成一个最高位开始全为1的二进制数,再加1即可。
/**
* Returns a power of two size for the given target capacity.
*/
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;
}