1:继承自AbstractMap类;允许null值,null的key和null的value均可;不保证元素有序;
2:get和put方法时间复杂度基本为o(1);通过hash将元素映射到对应的bucket;
3:initCapacity和loadFactor参数:initCapacity是hash表中bucket的初始数量;
【TODO】还没有理解这两个参数的意义!和源码有出入?为什么size>(capacity*factor)时候调整entry[]的大小?这样岂不是entry[]数组大小永远大于实际的元素数量?
4:实现了一个Entry
static class Entry<K, V> implements Map.Entry<K, V> {
final K key;
V value;
Entry<K, V> next;
final int hash;
}
5:确定一个元素要存到那个entry中:
int hash = hash(key.hashCode());//hash
int i = indexFor(hash, table.length);//根据hash值获得entry[]的下标记
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) {
return h & (length - 1);
}
6:插入元素时,有可能需要调整entry[]大小,重构entry[]
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);
<span style="color:#ff0000;">if (size++ >= threshold)//TODO 这个地方不太理解</span>
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);
}
/**
* Transfers all entries from current table to newTable.
*/
void transfer(Entry[] newTable) {
Entry[] src = table;
int newCapacity = newTable.length;
for (int j = 0; j < src.length; j++) {
Entry<K, V> e = src[j];
if (e != null) {
src[j] = null;
do {
Entry<K, V> next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);
}
}
}
7:获得元素
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
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.equals(k)))
return e.value;
}
return null;
}