参考:http://www.neversaydie.cc/hashmap-storage-mechanism/
http://www.cnblogs.com/violinn/archive/2013/05/27/3101980.html
1、HashMap两个重要的初始化参数(参考:http://blog.csdn.net/chenssy/article/details/18323767)
HashMap(int initialCapacity, float loadFactor):构造一个带指定初始容量和加载因子的空 HashMap。
在这里提到了两个参数:初始容量,加载因子。这两个参数是影响HashMap性能的重要参数,其中容量表示哈希表中桶的数量,初始容量是创建哈希表时的容量,加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,它衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之愈小。对于使用链表法的散列表来说,查找一个元素的平均时间是O(1+a),因此如果负载因子越大,对空间的利用更充分,然而后果是查找效率的降低;如果负载因子太小,那么散列表的数据将过于稀疏,对空间造成严重浪费。系统默认负载因子为0.75,一般情况下我们是无需修改的。
有一个解决办法是(http://www.neversaydie.cc/hashmap-storage-mechanism/):
先假设加载因子就是默认的0.75,当我们已经预知HashMap中元素的个数时,通过预设元素的个数可以有效的提高HashMap的性能。比如说,我们有1000个元素new HashMap(1000), 但是理论上来讲new HashMap(1024)更合适,不过笔者在上面已经说过,即使是1000,HashMap也自动会将其设置为1024。 但是new HashMap(1024)还不是更合适的,因为0.75*1000 < 1000, 也就是说为了让0.75 * size > 1000, 我们必须这样new HashMap(2048)才最合适,既考虑了&的问题,也避免了resize()方法和transfer()方法的问题。
2、hashmap的容量控制为2的倍数,为什么呢?
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);
// Find a power of 2 >= initialCapacity
int capacity = 1;
while (capacity < initialCapacity)//容量控制为2的倍数
capacity <<= 1;
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor);
table = new Entry[capacity];
init();
}
目的:为了寻址的快速,寻址是通过 index & (table.length-1)实现的,其实就是一个取模,如果table.length 是2的倍数的话,table.length-1 总是 111111... 的结构,与运算可以方便的得到mod值。
/**
* Returns index for hash code h.
*/
static int indexFor(int h, int length) {
return h & (length-1);
}