按HashMap源码里的那种重构方法,如果reHash过多,显然会影响性能。所以为了防止过多的reHash,我们需要自己配置HashMap的装载因子loadFactor和初始的table容量capacity的大小(可以在构造函数里配或者调用方法配)。
很容易理解,如果我们已经知道我们使用的HashMap一般情况的存储在1W对以上,你给它一个默认的16的初始的table容量,默认reHash每次容量翻倍,这得重构多少次呀!(如果装载因子为1,还得要约5~6次)。但是如果我们的对HashMap的容量需求不是很大,你给它一个默认1W的容量,显然又浪费宝贵的空间了。至于这两个参数的选择可以自己去把握,甚至可以设定动态绑定:分析历史数据,找出规律,或者预测未来的走向找出规律。对HashMap这两个参数实现一个动态的调整。比如早上8点~9点A业务比较忙,它对应的HashMap可以提前多给些空间,而10点以后B业务使用的HashMap比较忙,A相对清闲,可以缩减A的空间给B。
如果从数据库的表中读取记录存入HashMap中,完全可以根据记录的行数(row size)来初始化HashMap的容量,这样就可以达到reHash的最少次数,同时也保证了HashMap所需的最小容量:
比如:通过SQL语句: select count(字段) as rowSize from 表
提到行数: rowSize = 30
那么我们在定义HashMap的时候: HashMap<String,String> h = new HashMap<String,String>(rowSize,1f);
下面是HashMap的相关源代码部分:
_____________________________________________
//HashMap的构造
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)
capacity <<= 1;
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor);
table = new Entry[capacity];
init();
}
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
//添加新的项目
void addEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
if (size++ >= threshold) //注意理解这里,当前的实际大小(size)与threshold相等时,就将当前的容量扩大一倍
{
resize(2 * table.length);
}
}
//重构大小
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
Entry[] newTable = new Entry[newCapacity];
transfer(newTable);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
分享到:
相关推荐
上午: Map 集合 key-value key 无序无重复 value 无序可重复 ...HashMap(int initalCapacity,float loadFactor)具有指定的初始容量和负载因子 HashMap(Map,?extends V> m)HashMap与指定相同的映射 Map 4.常用方法
主要介绍了java在hashmap初始化时赋初值过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
java hashmap 扩容因子为什么是0.75,官方给出的解释
主要介绍了java中hashmap容量的初始化实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
记得刚毕业那会准备面试,看过不少面试题,里面有个说出HashMap和HashTable不同的题目,我那会面试的时候也遇到不少次这个问题,还隐约记得当时的回答是这样的: HashTable是比较旧的版本;HashTable是线程安全的,...
initialCapacity表示的是初始化的容量,默认是1<<4(也就是16); loadFactor表示的是扩容因子,默认是0.75f(也就是面试常问的3/4) 为啥扩容因子默认是0.75f?(HashMap的源码翻译) 假如你创建HashMap的...
HashMap介绍和使用
经典讲解List和ArrayList和Vector和HashTable和HashMap区别
if (删除元素的条件) {反例2. 【推荐】集合初始化时,指定集合初始值大小说明HashMap使用HashMap(int initialCapacity) 初
如果我们使用指定初始化容量的实例构造函数,可以传入一个指定的值,但是实际HashMap在初始化底层存储数据的数组时,会使用一个大于等于指定值的2的幂的数作为数组的初始化容量。并且如果HashMap中元素的个数大于...
Hashtable和HashMap区别以及他们的具体介绍
hashMap和hashTable的区别,大家可以下载学习学习。
HashTable不支持空键值对! 而HashMap支持空键值对!
HashMap是一个散列桶(数组和链表),它存储的内容是键值对(key-value)映射HashMap采用了数组和链表的数据结构,能在查询和修改方便继承了数组的线性查找和链表的寻址修改HashMap是非synchronized,所以HashMap很快...
Javascript实现和操作HashMap,压缩包里面有hashmap定义和操作的例子
Java集合专题总结:HashMap 和 HashTable 源码学习和面试总结
hashmap实例 hashmap实例hashmap实例hashmap实例
hashmap的底层及源码解析,很适合大家的学习,不要积分。
HashMap数据结构,HashMap的构造方法,HashMap的put,HashMap的get
hashMap = new HashMap ( capacity , loadFactor ) ; hashMap . put ( "someKey" , "Some variable" ) ; hashMap . get ( "someKey" ) ; >> 'Some variable' 哈希图可以自动调整大小。 但是你可以手动调用它: ...