构造函数:
public HashMap() {
table = (HashMapEntry<K, V>[]) EMPTY_TABLE;
threshold = -1; // Forces first put invocation to replace EMPTY_TABLE
}
可以看到他其实是一个实体数组,来存储hasmap里面的元素的。
添加元素
@Override public V put(K key, V value) {
if (key == null) {
return putValueForNullKey(value);
}
int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
int index = hash & (tab.length - 1);
for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
if (e.hash == hash && key.equals(e.key)) {
preModify(e);
V oldValue = e.value;
e.value = value;
return oldValue;
}
}
可以看到hash值的获得是通过:
Collections.secondaryHash(key)
也就是要二次hash获得的,
private static int secondaryHash(int h) {
// Spread bits to regularize both segment and index locations,
// using variant of single-word Wang/Jenkins hash.
h += (h << 15) ^ 0xffffcd7d;
h ^= (h >>> 10);
h += (h << 3);
h ^= (h >>> 6);
h += (h << 2) + (h << 14);
return h ^ (h >>> 16);
}
其中h为Key的hashcode.这样做的目的是为了让所有的位数都来参加hash。防止冲突
接着就是位置的获得:
int index = hash & (tab.length - 1);
这里面很巧妙,因为tab.length-1与任何数想与都小于length.