概述
HashMap是基于Map接口的实现。这个实现提供了所有可选的映射操作,并且允许null值和null键。(除了不同步和允许空值以外,HashMap和Hashtable几乎等价)。这个类不保证映射之间的顺序;尤其是,它不保证随着时间的推移映射顺序不变(翻译自Java API文档)。
哈希表是一个“链表散列”的结构,是由数组和链表结合而成。
HashMap的基层是一个数组结构,而数组中的每一项又可以拓展成为一个链表。具体的实现形式Entry就是数组中的元素,它是由key和value组成的基本单元,其本身持有Entry的引用来构成链表形式。
基本方法实现
此处源码版本为JDK1.7。
put方法
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
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;
}
其实现的过程如下:
首先检测key值,并由此得出它在数组中的index值,判断是否已有key存在,若已在则覆盖;若不存在则将新元素加到链表后,加元素操作具体由addEntry方法实现。
在addEntry方法中包含有扩容判断和createEntry方法,createEntry方法将新创建的 Entry 放入 bucketIndex 索引处,并让这个新的 Entry 指向原来的 Entry。
get方法
public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key);
return null == entry ? null : entry.getValue();
}
final Entry<K,V> getEntry(Object key) {
if (size == 0) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
get方法中用getEntry来判断key值在原数组中是否已存在并做取值操作。
总体来说,HashMap的底层是用Entry数组来实现的,通过key的哈希函数来寻找指定的key-value对位置并进行操作。
HashMap的refresh操作
当HashMap中的元素个数超过数组大小乘以负载因子时,就需要对HashMap进行扩容,类似的操作在List中也有。
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, initHashSeedAsNeeded(newCapacity));
table = newTable;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
新建Entry数组后将原数组中的元素转移到新数组中,即重新计算它们在新数组中的位置。默认的负载因子是0.75,扩容规模为原来的2倍。
以上为对HashMap实现的基本理解,更详细的内容参考http://zhangshixi.iteye.com/blog/672697