null Key/Value(Hashtable 不允許)ConcurrentHashMap 或 Collections.synchronizedMap)fail-fast:結構修改時拋 ConcurrentModificationExceptioncapacity 成正比,初始容量過大反而降低遍歷效能Entry<K,V>[] table 為桶數組,衝突以單鏈表形式存儲。JDK 1.7 使用頭插法,擴容時鏈表順序反轉,高併發下可能形成環導致 CPU 100%(JDK 1.8 改為尾插+紅黑樹)。
static class Entry<K,V> implements Map.Entry<K,V> {
final K key; V value; Entry<K,V> next; int hash;
Entry(int h, K k, V v, Entry<K,V> n) { value=v; next=n; key=k; hash=h; }
}
public V get(Object key) {
if (key == null) return getForNullKey(); // table[0] 遍歷
Entry<K,V> e = getEntry(key);
return e == null ? null : e.value;
}
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key);
for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next)
if (e.hash == hash && (e.key == key || key.equals(e.key))) return e;
return null;
}
public V put(K key, V value) {
if (table == EMPTY_TABLE) inflateTable(threshold);
if (key == null) return putForNullKey(value);
int hash = hash(key), i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next)
if (e.hash == hash && (e.key == key || key.equals(e.key))) {
V old = e.value; e.value = value; e.recordAccess(this); return old;
}
modCount++; addEntry(hash, key, value, i); return null;
}
void addEntry(int hash, K key, V value, int bucketIndex) {
if (size >= threshold && table[bucketIndex] != null) {
resize(2 * table.length); // 擴容 2 倍
hash = (key == null) ? 0 : hash(key);
bucketIndex = indexFor(hash, table.length);
}
createEntry(hash, key, value, bucketIndex);
}
void createEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<>(hash, key, value, e); // 頭插
size++;
}
final int hash(Object k) {
int h = hashSeed;
if (h != 0 && k instanceof String) return sun.misc.Hashing.stringHash32((String)k);
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12); // 攪亂高位降低衝突
return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) { return h & (length - 1); } // length 必須 2^n
void resize(int newCapacity) {
Entry[] old = table; int oldCap = old.length;
if (oldCap == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; }
Entry[] neu = new Entry[newCapacity];
transfer(neu, initHashSeedAsNeeded(newCapacity));
table = neu;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
void transfer(Entry[] newTable, boolean rehash) {
for (Entry<K,V> e : table) while (e != null) {
Entry<K,V> next = e.next;
if (rehash) e.hash = (e.key == null) ? 0 : hash(e.key);
int i = indexFor(e.hash, newTable.length);
e.next = newTable[i]; newTable[i] = e; // 頭插遷移
e = next;
}
}
HashIterator 統一邏輯:expectedModCount 實現 fail-fast,index 掃描桶數組,next 沿鏈表推進。keySet/values/entrySet 為三種視圖,支援 remove/clear,不支援 add。
1<<4),最大 2^30threshold = capacity * loadFactor 觸發擴容roundUpToPowerOf2 向上取 2 的冪