1、HashMap 类结构
/**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE; //用来存储Entry
final float loadFactor; //负载因子 当数组容量的占用比例超过负载因子时,数组就会扩容。
static class Entry<K,V> implements Map.Entry<K,V> {
final K key; //用来存储Key
V value; //用来存储Value
Entry<K,V> next; //用来指向:相同hashCode的Key,但是不同Key对象
int hash; //Key对象的hashCode值
/**
* Creates new entry.
*/
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
}
}
2、put(K key, V value)代码分析
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;
}
首先通过int hash = hash(key);计算Key对象的hashCode值。注:hashCode()的默认行为是对在heap上的对象产生独特的值。
然后通过int i = indexFor(hash, table.length);计算该hashCode值存放在entry数组的哪个位置。
然后通过for (Entry<K,V> e = table[i]; e != null; e = e.next)判断该数组位置上的所有Entry对象
(1)若hashCode相同,并且两个Key对象equals,那么就覆盖该key关联的value对象
(2)若hashCode相同,但两个Key对象not equals,那么就执行addEntry(hash, key, value, i);
最后:
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);
}
(1)首先拿到该数组位置的Entry值e
(2)然后将该entry值e传递给新要添加的Entry值,并使next指向该entry值e,代码如上面的Entry构造方法
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}