HashMap - juedaiyuer/researchNote GitHub Wiki
##hashMap笔记##

Java HashMap工作原理及实现(evernote)
public class hashmap {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("语文", 1);
map.put("数学", 2);
map.put("英语", 3);
map.put("历史", 4);
map.put("政治", 5);
map.put("地理", 6);
map.put("生物", 7);
map.put("化学", 8);
//增强的for循环;entrySet实现了Set接口,里面存放了键值对k-v
for(Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
- HashMap参数,容量Capacity,负载因子Load factor。这两个参数影响HashMap性能的重要参数
哈希表

哈希表是如何确定自己存储到哪一个数组节点中
- key%len
hashmap随机存取
//存储时:
int hash = key.hashCode();// 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值
int index = hash % Entry[].length;
Entry[index] = value;
//取值时:
int hash = key.hashCode();
int index = hash % Entry[].length;
return Entry[index];
##源码分析##
// HashMap构造函数源码
public HashMap(int initialCapacity, float loadFactor) {
//初始容量不能<0
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: "
+ initialCapacity);
//初始容量不能 > 最大容量值,HashMap的最大容量值为2^30
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
//负载因子不能 < 0
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: "
+ loadFactor);
// 计算出大于 initialCapacity 的最小的 2 的 n 次方值。
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
this.loadFactor = loadFactor;
//设置HashMap的容量极限,当HashMap的容量达到该极限时就会进行扩容操作
threshold = (int) (capacity * loadFactor);
//初始化table数组
table = new Entry[capacity];
init();
}
/**
* 存储实现put(key,value)
*/
public V put(K key, V value)
{
// 如果key为null,调用putForNullKey方法进行处理,保存null与table第一个位置中,这是HashMap允许为null的原因
if (key == null)
return putForNullKey(value);
// 根据key的keyCode计算Hash值
int hash = hash(key.hashCode());
// 搜索指定hash值在对应table中的索引
int i = indexFor(hash, table.length);
// 如果i索引处的Entry不为null,通过循环不断遍历e元素的下一个元素
for (Entry<K,V> e = table[i]; e != null; e = e.next)
{
Object k;
//找到指定key与需要放入的key相等(hash值相同,通过equals比较放回true)
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
{
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
// 修改次数增加1
modCount++;
// 将key、value添加到i索引处
addEntry(hash, key, value, i);
return null;
}
- 优雅设计:新添加的Entry对象放入table数组bucketIndex索引处,而最早放入该 bucket 中的 Entry 则位于这个 Entry 链的最末端
- 添加位置由K-V对的Value决定
- HashMap里面实现一个静态内部类Entry,其重要的属性有 key , value, next,Entry就是HashMap键值对实现的一个基础bean,我们上面说到HashMap的基础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存在Entry[]里面。
addEntry源代码
void addEntry(int hash, K key, V value, int bucketIndex)
{
// 获取指定 bucketIndex 索引处的 Entry
Entry<K,V> e = table[bucketIndex];
// 将新创建的 Entry 放入 bucketIndex 索引处,并让新的 Entry 指向原来的 Entry
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
// 如果 Map 中的 key-value 对的数量超过了极限
if (size++ >= threshold)
// 把 table 对象的长度扩充到 2 倍。
resize(2 * table.length);
}
##source##