# çå®è¿ç¯ HashMapï¼åé¢è¯å®æ¯ç®å°±æ²¡é®é¢äº
* [çå®è¿ç¯ HashMapï¼åé¢è¯å®æ¯ç®å°±æ²¡é®é¢äº](#çå®è¿ç¯-hashmapåé¢è¯å®æ¯ç®å°±æ²¡é®é¢äº)
* [HashMap æ¦è¿°](#hashmap-æ¦è¿°)
* [HashMap å HashTable çåºå«](#hashmap-å-hashtable-çåºå«)
* [ç¸åç¹](#ç¸åç¹)
* [ä¸åç¹](#ä¸åç¹)
* [HashMap å HashSet çåºå«](#hashmap-å-hashset-çåºå«)
* [HashMap åºå±ç»æ](#hashmap-åºå±ç»æ)
* [AbstractMap ç±»](#abstractmap-ç±»)
* [Map æ¥å£](#map-æ¥å£)
* [éè¦å
é¨ç±»åæ¥å£](#éè¦å
é¨ç±»åæ¥å£)
* [Node æ¥å£](#node-æ¥å£)
* [KeySet å
é¨ç±»](#keyset-å
é¨ç±»)
* [Values å
é¨ç±»](#values-å
é¨ç±»)
* [EntrySet å
é¨ç±»](#entryset-å
é¨ç±»)
* [HashMap 1.7 çåºå±ç»æ](#hashmap-17-çåºå±ç»æ)
* [HashMap 1.8 çåºå±ç»æ](#hashmap-18-çåºå±ç»æ)
* [HashMap éè¦å±æ§](#hashmap-éè¦å±æ§)
* [HashMap æé 彿°](#hashmap-æé 彿°)
* [讲ä¸è®² HashMap put çå
¨è¿ç¨](#讲ä¸è®²-hashmap-put-çå
¨è¿ç¨)
* [Hash 彿°](#hash-彿°)
* [æ©å®¹æºå¶](#æ©å®¹æºå¶)
* [讲ä¸è®² get æ¹æ³å
¨è¿ç¨](#讲ä¸è®²-get-æ¹æ³å
¨è¿ç¨)
* [HashMap çéåæ¹å¼](#hashmap-çéåæ¹å¼)
* [HashMap ä¸çç§»é¤æ¹æ³](#hashmap-ä¸çç§»é¤æ¹æ³)
* [å
³äº HashMap çé¢è¯é¢](#å
³äº-hashmap-çé¢è¯é¢)
* [HashMap çæ°æ®ç»æ](#hashmap-çæ°æ®ç»æ)
* [HashMap ç put è¿ç¨](#hashmap-ç-put-è¿ç¨)
* [HashMap 为å¥çº¿ç¨ä¸å®å
¨](#hashmap-为å¥çº¿ç¨ä¸å®å
¨)
* [HashMap æ¯å¦ä½å¤çåå¸ç¢°æç](#hashmap-æ¯å¦ä½å¤çåå¸ç¢°æç)
* [HashMap æ¯å¦ä½ get å
ç´ ç](#hashmap-æ¯å¦ä½-get-å
ç´ ç)
* [HashMap å HashTable æä»ä¹åºå«](#hashmap-å-hashtable-æä»ä¹åºå«)
* [HashMap å HashSet çåºå«](#hashmap-å-hashset-çåºå«-1)
* [HashMap æ¯å¦ä½æ©å®¹ç](#hashmap-æ¯å¦ä½æ©å®¹ç)
* [HashMap çé¿åº¦ä¸ºä»ä¹æ¯ 2 ç广¬¡æ¹](#hashmap-çé¿åº¦ä¸ºä»ä¹æ¯-2-ç广¬¡æ¹)
* [HashMap 线ç¨å®å
¨çå®ç°æåªäº](#hashmap-线ç¨å®å
¨çå®ç°æåªäº)
* [åè®°](#åè®°)
## HashMap æ¦è¿°
**å¦æä½ æ²¡ææ¶é´ç»æ æ¬æï¼å¯ä»¥ç´æ¥ç HashMap æ¦è¿°ï¼è½è®©ä½ 对 HashMap æä¸ªå¤§è´çäºè§£**ã
HashMap æ¯ Map æ¥å£çå®ç°ï¼HashMap å
许空ç key-value é®å¼å¯¹ï¼HashMap è¢«è®¤ä¸ºæ¯ Hashtable çå¢å¼ºçï¼HashMap æ¯ä¸ä¸ªé线ç¨å®å
¨ç容å¨ï¼å¦ææ³æé 线ç¨å®å
¨ç Map èèä½¿ç¨ ConcurrentHashMapãHashMap æ¯æ åºçï¼å 为 HashMap æ æ³ä¿è¯å
é¨åå¨çé®å¼å¯¹çæåºæ§ã
HashMap çåºå±æ°æ®ç»ææ¯æ°ç» + é¾è¡¨çéåä½ï¼æ°ç»å¨ HashMap ä¸å被称为`æ¡¶(bucket)`ãéå HashMap éè¦çæ¶é´æè为 HashMap å®ä¾æ¡¶çæ°é + (key - value æ å°) çæ°éãå æ¤ï¼å¦æéåå
ç´ å¾éè¦çè¯ï¼ä¸è¦æåå§å®¹é设置çå¤ªé«æè
è´è½½å å设置ç太ä½ã
HashMap å®ä¾æä¸¤ä¸ªå¾éè¦çå ç´ ï¼åå§å®¹éåè´è½½å åï¼åå§å®¹éæçå°±æ¯ hash è¡¨æ¡¶çæ°éï¼è´è½½å 忝ä¸ç§è¡¡éåå¸è¡¨å¡«å
ç¨åº¦çæ åï¼å½åå¸è¡¨ä¸åå¨è¶³å¤æ°éç entryï¼ä»¥è³äºè¶
è¿äºè´è½½å ååå½å容éï¼è¿ä¸ªåå¸è¡¨ä¼è¿è¡ rehash æä½ï¼å
é¨çæ°æ®ç»æéæ° rebuiltã
注æ HashMap 䏿¯çº¿ç¨å®å
¨çï¼å¦æå¤ä¸ªçº¿ç¨åæ¶å½±åäº HashMap ï¼å¹¶ä¸è³å°ä¸ä¸ªçº¿ç¨ä¿®æ¹äº HashMap çç»æï¼é£ä¹å¿
须对 HashMap è¿è¡åæ¥æä½ãå¯ä»¥ä½¿ç¨ `Collections.synchronizedMap(new HashMap)` æ¥å建ä¸ä¸ªçº¿ç¨å®å
¨ç Mapã
HashMap ä¼å¯¼è´é¤äºè¿ä»£å¨æ¬èº«ç remove å¤ï¼å¤é¨ remove æ¹æ³é½å¯è½ä¼å¯¼è´ fail-fast æºå¶ï¼å æ¤å°½éè¦ç¨è¿ä»£å¨èªå·±ç remove æ¹æ³ã妿å¨è¿ä»£å¨å建çè¿ç¨ä¸ä¿®æ¹äº map çç»æï¼å°±ä¼æåº `ConcurrentModificationException` å¼å¸¸ã
ä¸é¢å°±æ¥èä¸è HashMap çç»èé®é¢ãæä»¬è¿æ¯ä»é¢è¯é¢å
¥ææ¥åæ HashMap ã
## HashMap å HashTable çåºå«
æä»¬ä¸é¢ä»ç»äºä¸ä¸ HashMap ï¼ç°å¨æ¥ä»ç»ä¸ä¸ HashTable
### ç¸åç¹
HashMap å HashTable 齿¯åºäºåå¸è¡¨å®ç°çï¼å
¶å
鍿¯ä¸ªå
ç´ é½æ¯ `key-value` é®å¼å¯¹ï¼HashMap å HashTable é½å®ç°äº MapãCloneableãSerializable æ¥å£ã
### ä¸åç¹
* ç¶ç±»ä¸åï¼HashMap ç»§æ¿äº `AbstractMap` ç±»ï¼è HashTable ç»§æ¿äº `Dictionary` ç±»

* 空å¼ä¸åï¼HashMap å
许空ç key å value å¼ï¼HashTable ä¸å
许空ç key å value å¼ãHashMap 伿 Null key å½åæ®éç key 对å¾
ãä¸å
许 null key éå¤ã

* 线ç¨å®å
¨æ§ï¼HashMap 䏿¯çº¿ç¨å®å
¨çï¼å¦æå¤ä¸ªå¤é¨æä½åæ¶ä¿®æ¹ HashMap çæ°æ®ç»ææ¯å¦ add æè
æ¯ deleteï¼å¿
é¡»è¿è¡åæ¥æä½ï¼ä»
ä»
对 key æè
value çä¿®æ¹ä¸æ¯æ¹åæ°æ®ç»æçæä½ãå¯ä»¥éæ©æé 线ç¨å®å
¨ç Map æ¯å¦ `Collections.synchronizedMap` æè
æ¯ `ConcurrentHashMap`ãè HashTable æ¬èº«å°±æ¯çº¿ç¨å®å
¨ç容å¨ã
* æ§è½æ¹é¢ï¼è½ç¶ HashMap å HashTable 齿¯åºäºåé¾è¡¨çï¼ä½æ¯ HashMap è¿è¡ put æè
getô±¤ æä½ï¼å¯ä»¥è¾¾å°å¸¸æ°æ¶é´çæ§è½ï¼è HashTable ç put å get æä½é½æ¯å äº `synchronized` éçï¼æä»¥æçå¾å·®ã

* åå§å®¹éä¸åï¼HashTable çåå§é¿åº¦æ¯11ï¼ä¹åæ¯æ¬¡æ©å
容éå为ä¹åç 2n+1ï¼n为ä¸ä¸æ¬¡çé¿åº¦ï¼
è HashMap çåå§é¿åº¦ä¸º16ï¼ä¹åæ¯æ¬¡æ©å
åä¸ºåæ¥ç两åãå建æ¶ï¼å¦æç»å®äºå®¹éåå§å¼ï¼é£ä¹HashTable ä¼ç´æ¥ä½¿ç¨ä½ ç»å®ç大å°ï¼è HashMap ä¼å°å
¶æ©å
为2ç广¬¡æ¹å¤§å°ã
## HashMap å HashSet çåºå«
ä¹ç»å¸¸ä¼é®å° HashMap å HashSet çåºå«
HashSet ç»§æ¿äº AbstractSet æ¥å£ï¼å®ç°äº SetãCloneable,ãjava.io.Serializable æ¥å£ãHashSet ä¸å
许éåä¸åºç°éå¤çå¼ãHashSet åºå±å
¶å®å°±æ¯ HashMapï¼ææå¯¹ HashSet çæä½å
¶å®å°±æ¯å¯¹ HashMap çæä½ãæä»¥ HashSet ä¹ä¸ä¿è¯éåç顺åºã
## HashMap åºå±ç»æ
è¦äºè§£ä¸ä¸ªç±»ï¼å
è¦äºè§£è¿ä¸ªç±»çç»æï¼å
æ¥çä¸ä¸ HashMap çç»æï¼

æä¸»è¦çä¸ä¸ªç±»(æ¥å£)å°±æ¯ `HashMap`,`AbstractMap`å `Map` äºï¼HashMap æä»¬ä¸é¢å·²ç»å¨æ¦è¿°ä¸ç®åä»ç»äºä¸ä¸ï¼ä¸é¢æ¥ä»ç»ä¸ä¸ AbstractMapã
### AbstractMap ç±»
è¿ä¸ªæ½è±¡ç±»æ¯ Map æ¥å£ç骨干å®ç°ï¼ä»¥æ±æå¤§åçåå°å®ç°ç±»çå·¥ä½éã为äºå®ç°ä¸å¯ä¿®æ¹ç mapï¼ç¨åºåä»
éè¦ç»§æ¿è¿ä¸ªç±»å¹¶ä¸æä¾ entrySet æ¹æ³çå®ç°å³å¯ãå®å°ä¼è¿åä¸ç» map æ å°çæä¸æ®µãé常ï¼è¿åçéåå°å¨AbstractSet ä¹ä¸å®ç°ãè¿ä¸ªsetä¸åºè¯¥æ¯æ add æè
remove æ¹æ³ï¼å¹¶ä¸å®çè¿ä»£å¨ä¹ä¸æ¯æ remove æ¹æ³ã
为äºå®ç°å¯ä¿®æ¹ç mapï¼ç¨åºåå¿
é¡»é¢å¤éåè¿ä¸ªç±»ç put æ¹æ³(å¦å就伿åºUnsupportedOperationException)ï¼å¹¶ä¸ entrySet.iterator() è¿åç iterator å¿
é¡»å®ç° remove() æ¹æ³ã
### Map æ¥å£
Map æ¥å£å®ä¹äº key-value é®å¼å¯¹çæ åãä¸ä¸ªå¯¹è±¡æ¯æ key-value åå¨ãMapä¸è½å
å«éå¤ç keyï¼æ¯ä¸ªé®æå¤æ å°ä¸ä¸ªå¼ãè¿ä¸ªæ¥å£ä»£æ¿äºDictionary ç±»ï¼Dictionaryæ¯ä¸ä¸ªæ½è±¡ç±»è䏿¯æ¥å£ã
Map æ¥å£æä¾äºä¸ä¸ªéåçæé å¨ï¼å®å
è®¸å° map çå
容è§ä¸ºä¸ç»é®ï¼å¼éåæä¸ç»é®å¼æ å°ãmapç顺åºå®ä¹ä¸ºmapæ å°éåä¸çè¿ä»£å¨è¿åå
¶å
ç´ ç顺åºãä¸äºmapå®ç°ï¼åæ¯TreeMapç±»ï¼ä¿è¯äºmapçæåºæ§ï¼å
¶ä»çå®ç°ï¼åæ¯HashMapï¼å没æä¿è¯ã
### éè¦å
é¨ç±»åæ¥å£
#### Node æ¥å£
Nodeèç¹æ¯ç¨æ¥åå¨HashMapçä¸ä¸ªä¸ªå®ä¾ï¼å®å®ç°äº `Map.Entry`æ¥å£ï¼æä»¬å
æ¥çä¸ä¸ Mapä¸çå
鍿¥å£ Entry æ¥å£çå®ä¹
Map.Entry
```java
// ä¸ä¸ªmap çentry é¾ï¼è¿ä¸ªMap.entrySet()æ¹æ³è¿åä¸ä¸ªéåçè§å¾ï¼å
å«ç±»ä¸çå
ç´ ï¼
// è¿ä¸ªå¯ä¸çæ¹å¼æ¯ä»éåçè§å¾è¿è¡è¿ä»£ï¼è·åä¸ä¸ªmapçentryé¾ãè¿äºMap.Entryé¾åªå¨
// è¿ä»£æé´ææã
interface Entry {
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
}
```
Node èç¹ä¼åå¨åä¸ªå±æ§ï¼hashå¼ï¼keyï¼valueï¼æåä¸ä¸ä¸ªNodeèç¹çå¼ç¨
```java
// hashå¼
final int hash;
// é®
final K key;
// å¼
V value;
// æåä¸ä¸ä¸ªNodeèç¹çNodeç±»å
Node next;
```
å 为Map.Entry æ¯ä¸æ¡æ¡entry é¾è¿æ¥å¨ä¸èµ·çï¼æä»¥Nodeèç¹ä¹æ¯ä¸æ¡æ¡entryé¾ãæé ä¸ä¸ªæ°çHashMapå®ä¾çæ¶åï¼ä¼æè¿åä¸ªå±æ§å¼åä¸ºä¼ å
¥
```java
Node(int hash, K key, V value, Node next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
```
å®ç°äº Map.Entry æ¥å£æä»¥å¿
é¡»å®ç°å
¶ä¸çæ¹æ³ï¼æä»¥ Node èç¹ä¸ä¹å
æ¬ä¸é¢çäºä¸ªæ¹æ³
#### KeySet å
é¨ç±»
keySet 类继æ¿äº AbstractSet æ½è±¡ç±»ï¼å®æ¯ç± HashMap ä¸ç `keyset()` æ¹æ³æ¥å建 KeySet å®ä¾çï¼æ¨å¨å¯¹HashMap ä¸çkeyé®è¿è¡æä½ï¼çä¸ä¸ªä»£ç 示ä¾

å¾ä¸æ**1, 2, 3**è¿ä¸ä¸ªkey æ¾å¨äºHashMapä¸ï¼ç¶åä½¿ç¨ lambda 表达å¼å¾ªç¯éå key å¼ï¼å¯ä»¥çå°ï¼map.keySet() å
¶å®æ¯è¿åäºä¸ä¸ª Set æ¥å£ï¼KeySet() æ¯å¨ Map æ¥å£ä¸è¿è¡å®ä¹çï¼ä¸è¿æ¯è¢«HashMap è¿è¡äºå®ç°æä½ï¼æ¥çä¸ä¸æºç å°±æç½äº
```java
// è¿åä¸ä¸ªsetè§å¾ï¼è¿ä¸ªè§å¾ä¸å
å«äºmapä¸çkeyã
public Set keySet() {
// // keySet æåçæ¯ AbstractMap ä¸ç keyset
Set ks = keySet;
if (ks == null) {
// 妿 ks 为空ï¼å°±å建ä¸ä¸ª KeySet 对象
// 并对 ks èµå¼ã
ks = new KeySet();
keySet = ks;
}
return ks;
}
```
æä»¥ KeySet ç±»ä¸é½æ¯å¯¹ Mapä¸ç Key è¿è¡æä½çï¼

#### Values å
é¨ç±»
Values ç±»çå建å
¶å®æ¯å KeySet ç±»å¾ç¸ä¼¼ï¼ä¸è¿ KeySet æ¨å¨å¯¹ Mapä¸çé®è¿è¡æä½ï¼Values æ¨å¨å¯¹`key-value` é®å¼å¯¹ä¸ç value å¼è¿è¡ä½¿ç¨ï¼çä¸ä¸ä»£ç 示ä¾ï¼

循ç¯éå Mapä¸ç valueså¼ï¼çä¸ä¸ values() æ¹æ³æç»åå»ºçæ¯ä»ä¹ï¼
```java
public Collection values() {
// values å
¶å®æ¯ AbstractMap ä¸ç values
Collection vs = values;
if (vs == null) {
vs = new Values();
values = vs;
}
return vs;
}
```
ææç values å
¶å®é½åå¨å¨ AbstractMap ä¸ï¼è Values ç±»å
¶å®ä¹æ¯å®ç°äº Map ä¸ç Values æ¥å£ï¼çä¸ä¸å¯¹ values çæä½é½æåªäºæ¹æ³

å
¶å®æ¯å key çæä½å·®ä¸å¤
#### EntrySet å
é¨ç±»
ä¸é¢æå°äºHashMapä¸å嫿坹 keyãvalue è¿è¡æä½çï¼å
¶å®è¿æå¯¹ `key-value` é®å¼å¯¹è¿è¡æä½çå
é¨ç±»ï¼å®å°±æ¯ EntrySetï¼æ¥çä¸ä¸EntrySet çå建è¿ç¨ï¼

ç¹è¿å» entrySet() ä¼åç°è¿ä¸ªæ¹æ³ä¹æ¯å¨ Map æ¥å£ä¸å®ä¹çï¼HashMap对å®è¿è¡äºéå
```java
// è¿åä¸ä¸ª set è§å¾ï¼æ¤è§å¾å
å«äº map ä¸çkey-value é®å¼å¯¹
public Set> entrySet() {
Set> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
```
妿 es 为空å建ä¸ä¸ªæ°ç EntrySet å®ä¾ï¼EntrySet 主è¦å
æ¬äºå¯¹key-value é®å¼å¯¹æ å°çæ¹æ³ï¼å¦ä¸

### HashMap 1.7 çåºå±ç»æ
JDK1.7 ä¸ï¼HashMap éç¨ä½æ¡¶ + é¾è¡¨çå®ç°ï¼å³ä½¿ç¨é¾è¡¨æ¥å¤çå²çªï¼åä¸ hash å¼çé¾è¡¨é½åå¨å¨ä¸ä¸ªæ°ç»ä¸ã使¯å½ä½äºä¸ä¸ªæ¡¶ä¸çå
ç´ è¾å¤ï¼å³ hash å¼ç¸ççå
ç´ è¾å¤æ¶ï¼éè¿ key å¼ä¾æ¬¡æ¥æ¾çæçè¾ä½ãå®çæ°æ®ç»æå¦ä¸

HashMap åºå±æ°æ®ç»æå°±æ¯ä¸ä¸ª Entry æ°ç»ï¼Entry æ¯ HashMap çåºæ¬ç»æåå
ï¼æ¯ä¸ª Entry ä¸å
å«ä¸ä¸ª key-value é®å¼å¯¹ã
```java
transient Entry[] table = (Entry[]) EMPTY_TABLE;
```
èæ¯ä¸ª Entry ä¸å
å« **hash, key ,value** 屿§ï¼å®æ¯ HashMap çä¸ä¸ªå
é¨ç±»
```java
static class Entry implements Map.Entry {
final K key;
V value;
Entry next;
int hash;
Entry(int h, K k, V v, Entry n) {
value = v;
next = n;
key = k;
hash = h;
}
...
}
```
æä»¥ï¼HashMap çæ´ä½ç»æå°±åä¸é¢è¿æ ·

### HashMap 1.8 çåºå±ç»æ
ä¸ JDK 1.7 ç¸æ¯ï¼1.8 å¨åºå±ç»ææ¹é¢åäºä¸äºæ¹åï¼å½æ¯ä¸ªæ¡¶ä¸å
ç´ å¤§äº 8 çæ¶åï¼ä¼è½¬åä¸ºçº¢é»æ ï¼ç®çå°±æ¯ä¼åæ¥è¯¢æçï¼JDK 1.8 éåäº `resize()` æ¹æ³ã

### HashMap éè¦å±æ§
**åå§å®¹é**
HashMap çé»è®¤åå§å®¹éæ¯ç± `DEFAULT_INITIAL_CAPACITY` 屿§ç®¡ççã
```java
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
```
HashMaap çé»è®¤åå§å®¹éæ¯ 1 << 4 = 16ï¼ << æ¯ä¸ä¸ª`左移`æä½ï¼å®ç¸å½äºæ¯

**æå¤§å®¹é**
HashMap çæå¤§å®¹éæ¯
```java
static final int MAXIMUM_CAPACITY = 1 << 30;
```
è¿éæ¯ä¸æ¯æä¸ªçé®ï¼int å ç¨å个åèï¼æè¯´æå¤§å®¹éåºè¯¥æ¯å·¦ç§» 31 ä½ï¼ä¸ºä»ä¹ HashMap æå¤§å®¹éæ¯å·¦ç§» 30 ä½å¢ï¼å ä¸ºå¨æ°å¼è®¡ç®ä¸ï¼æé«ä½ä¹å°±æ¯æå·¦ä½ç`ä½` æ¯ä»£è¡¨ç符å·ä¸ºï¼0 -> æ£æ°ï¼1 -> è´æ°ï¼å®¹éä¸å¯è½æ¯è´æ°ï¼æä»¥ HashMap æé«ä½åªè½ç§»ä½å° 2 ^ 30 次å¹ã
**é»è®¤è´è½½å å**
HashMap çé»è®¤è´è½½å 忝
```java
static final float DEFAULT_LOAD_FACTOR = 0.75f;
```
float ç±»åæä»¥ç¨ `.f` 为åä½ï¼è´è½½å 忝忩容æºå¶æå
³ï¼è¿éå¤§è´æä¸ä¸ï¼åé¢ä¼ç»è¯´ãæ©å®¹æºå¶çååæ¯å½ HashMap ä¸åå¨çæ°é > HashMap 容é * è´è½½å åæ¶ï¼å°±ä¼æ HashMap çå®¹éæ©å¤§ä¸ºåæ¥çäºåã
HashMap çç¬¬ä¸æ¬¡æ©å®¹å°±å¨ DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR = 12 æ¶è¿è¡ã
**æ åéå¼**
HashMap çæ åé弿¯
```java
static final int TREEIFY_THRESHOLD = 8;
```
å¨è¿è¡æ·»å å
ç´ æ¶ï¼å½ä¸ä¸ªæ¡¶ä¸åå¨å
ç´ çæ°é > 8 æ¶ï¼ä¼èªå¨è½¬æ¢ä¸ºçº¢é»æ ï¼JDK1.8 ç¹æ§ï¼ã
**é¾è¡¨éå¼**
HashMap çé¾è¡¨é弿¯
```java
static final int UNTREEIFY_THRESHOLD = 6;
```
å¨è¿è¡å é¤å
ç´ æ¶ï¼å¦æä¸ä¸ªæ¡¶ä¸åå¨å
ç´ æ°é < 6 åï¼ä¼èªå¨è½¬æ¢ä¸ºé¾è¡¨
**æ©å®¹ä¸´çå¼**
```java
static final int MIN_TREEIFY_CAPACITY = 64;
```
è¿ä¸ªå¼è¡¨ç¤ºçæ¯å½æ¡¶æ°ç»å®¹éå°äºè¯¥å¼æ¶ï¼ä¼å
è¿è¡æ©å®¹ï¼è䏿¯æ å
**èç¹æ°ç»**
HashMap ä¸çèç¹æ°ç»å°±æ¯ Entry æ°ç»ï¼å®ä»£è¡¨çå°±æ¯ HashMap ä¸ **æ°ç» + é¾è¡¨** æ°æ®ç»æä¸çæ°ç»ã
```java
transient Node[] table;
```
Node æ°ç»å¨ç¬¬ä¸æ¬¡ä½¿ç¨çæ¶åè¿è¡åå§åæä½ï¼å¨å¿
è¦çæ¶åè¿è¡ `resize`ï¼resize åæ°ç»çé¿åº¦æ©å®¹ä¸ºåæ¥çäºåã
**é®å¼å¯¹æ°é**
å¨ HashMap ä¸ï¼ä½¿ç¨ `size` æ¥è¡¨ç¤º HashMap ä¸é®å¼å¯¹çæ°éã
**ä¿®æ¹æ¬¡æ°**
å¨ HashMap ä¸ï¼ä½¿ç¨ `modCount` æ¥è¡¨ç¤ºä¿®æ¹æ¬¡æ°ï¼ä¸»è¦ç¨äºåå¹¶åä¿®æ¹ HashMap æ¶çå¿«é失败 - fail-fast æºå¶ã
**æ©å®¹éå¼**
å¨ HashMap ä¸ï¼ä½¿ç¨ `threshold` 表示æ©å®¹çéå¼ï¼ä¹å°±æ¯ åå§å®¹é * è´è½½å åçå¼ã
threshold æ¶åå°ä¸ä¸ªæ©å®¹çéå¼é®é¢ï¼è¿ä¸ªé®é¢æ¯ç± `tableSizeFor` æºç è§£å³çãæä»¬å
çä¸ä¸å®çæºç åæ¥è§£é
```java
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
```
代ç 䏿¶åä¸ä¸ªè¿ç®ç¬¦ `|=` ï¼å®è¡¨ç¤ºçæ¯æä½æï¼å¥ææå¢ï¼ä½ ä¸å®ç¥é **a+=b çæææ¯ a=a+b**ï¼é£ä¹ **åçï¼a |= b å°±æ¯ a = a | b **ï¼ä¹å°±æ¯åæ¹é½è½¬æ¢ä¸ºäºè¿å¶ï¼æ¥è¿è¡ä¸æä½ãå¦ä¸å¾æç¤º

æä»¬ä¸é¢éç¨äºä¸ä¸ªæ¯è¾å¤§çæ°åè¿è¡æ©å®¹ï¼ç±ä¸å¾å¯ç¥ 2^29 次æ¹çæ°ç»ç»è¿ä¸ç³»åçææä½åï¼ä¼ç®åºæ¥ç»ææ¯ 2^30 次æ¹ã
æä»¥æ©å®¹åçæ°ç»é¿åº¦æ¯åæ¥ç 2 åã
**è´è½½å å**
`loadFactor` 表示è´è½½å åï¼å®è¡¨ç¤ºçæ¯ HashMap ä¸çå¯éç¨åº¦ã
### HashMap æé 彿°
å¨ HashMap æºç ä¸ï¼æåç§æé 彿°ï¼å嫿¥ä»ç»ä¸ä¸
* 带æ`åå§å®¹é initialCapacity` å `è´è½½å å loadFactor` çæé 彿°
```java
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
// æ©å®¹çéå¼
this.threshold = tableSizeFor(initialCapacity);
}
```
åå§å®¹éä¸è½ä¸ºè´ï¼æä»¥å½ä¼ éåå§å®¹é < 0 çæ¶åï¼ä¼ç´æ¥æåº `IllegalArgumentException` å¼å¸¸ãå¦æä¼ éè¿æ¥çåå§å®¹é > æå¤§å®¹éæ¶ï¼åå§å®¹é = æå¤§å®¹éãè´è½½å åä¹ä¸è½å°äº 0 ãç¶åè¿è¡æ°ç»çæ©å®¹ï¼è¿ä¸ªæ©å®¹æºå¶ä¹é常éè¦ï¼æä»¬åé¢è¿è¡æ¢è®¨
* åªå¸¦æ initialCapacity çæé 彿°
```java
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
```
æç»ä¹ä¼è°ç¨å°ä¸é¢çæé 彿°ï¼ä¸è¿è¿ä¸ªé»è®¤çè´è½½å åå°±æ¯ HashMap çé»è®¤è´è½½å åä¹å°±æ¯ `0.75f`
* æ åæ°çæé 彿°
```java
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
```
é»è®¤çè´è½½å åä¹å°±æ¯ 0.75f
* 带æ map çæé 彿°
```java
public HashMap(Map extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);
}
```
带æ Map çæé 彿°ï¼ä¼ç´æ¥æå¤é¨å
ç´ æ¹éæ¾å
¥ HashMap ä¸ã
### 讲ä¸è®² HashMap put çå
¨è¿ç¨
æè®°å¾åæ¯ä¸ä¸å¹´å»å京é¢è¯ï¼ä¸å®¶å
¬å¸é®æ HashMap put è¿ç¨çæ¶åï¼ææ¯æ¯å¾å¾çä¸ä¸æ¥ï¼åé¢çä¸å³å¿å¥½å¥½æ´ã以 JDK 1.8 为åºåè¿è¡åæï¼åé¢ä¹æ¯ãå
è´´åºæ´æ®µä»£ç ï¼åé¢ä¼éè¡è¿è¡åæã
```java
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node[] tab; Node p; int n, i;
// 妿table 为null æè
没æä¸º table åé
å
åï¼å°±resize䏿¬¡
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// æå®hashå¼èç¹ä¸ºç©ºåç´æ¥æå
¥ï¼è¿ä¸ª(n - 1) & hashææ¯è¡¨ä¸çæ£çåå¸
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
// 妿ä¸ä¸ºç©º
else {
Node e; K k;
// 计ç®è¡¨ä¸çè¿ä¸ªçæ£çåå¸å¼ä¸è¦æå
¥çkey.hashç¸æ¯
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
// è¥ä¸åçè¯ï¼å¹¶ä¸å½åèç¹å·²ç»å¨ TreeNode ä¸äº
else if (p instanceof TreeNode)
// éç¨çº¢é»æ å卿¹å¼
e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
// key.hash ä¸åå¹¶ä¸ä¹ä¸å TreeNode ä¸ï¼å¨é¾è¡¨ä¸æ¾å° p.next==null
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
// å¨è¡¨å°¾æå
¥
p.next = newNode(hash, key, value, null);
// æ°å¢èç¹å妿èç¹ä¸ªæ°å°è¾¾éå¼ï¼åè¿å
¥ treeifyBin() è¿è¡åæ¬¡å¤æ
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
// 妿æ¾å°äºå hashãkey çèç¹ï¼é£ä¹ç´æ¥éåºå¾ªç¯
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
// æ´æ° p æåä¸ä¸èç¹
p = e;
}
}
// mapä¸å«ææ§å¼ï¼è¿åæ§å¼
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
// mapè°æ´æ¬¡æ° + 1
++modCount;
// é®å¼å¯¹çæ°éè¾¾å°éå¼ï¼éè¦æ©å®¹
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
```
é¦å
çä¸ä¸ `putVal` æ¹æ³ï¼è¿ä¸ªæ¹æ³æ¯ final çï¼å¦æä½ èªå·²å®ä¹ HashMap ç»§æ¿çè¯ï¼æ¯ä¸å
è®¸ä½ èªå·±éå put æ¹æ³çï¼ç¶åè¿ä¸ªæ¹æ³æ¶åäºä¸ªåæ°
* hash -> put æ¾å¨æ¡¶ä¸çä½ç½®ï¼å¨ put ä¹åï¼ä¼è¿è¡ hash 彿°ç计ç®ã
* key -> åæ°ç key å¼
* value -> åæ°ç value å¼
* onlyIfAbsent -> æ¯å¦æ¹åå·²ç»åå¨çå¼ï¼ä¹å°±æ¯æ¯å¦è¿è¡ value å¼çæ¿æ¢æ å¿
* evict -> æ¯å¦æ¯åå建 HashMap çæ å¿
å¨è°ç¨å° putVal æ¹æ³æ¶ï¼é¦å
ä¼è¿è¡ hash 彿°è®¡ç®åºè¯¥æå
¥çä½ç½®
```java
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
```
åå¸å½æ°çæºç å¦ä¸
```java
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
```
é¦å
å
æ¥çè§£ä¸ä¸ hash 彿°ç计ç®è§å
#### Hash 彿°
hash 彿°ä¼æ ¹æ®ä½ ä¼ éç key å¼è¿è¡è®¡ç®ï¼é¦å
è®¡ç® key ç `hashCode` å¼ï¼ç¶åå对 hashcode è¿è¡æ 符å·å³ç§»æä½ï¼æååå hashCode è¿è¡`弿 ^` æä½ã
>`>>>`: æ 符å·å³ç§»æä½ï¼å®æçæ¯ **æ 符å·å³ç§»ï¼ä¹å«é»è¾å³ç§»ï¼å³è¥è¯¥æ°ä¸ºæ£ï¼åé«ä½è¡¥0ï¼èè¥è¯¥æ°ä¸ºè´æ°ï¼åå³ç§»åé«ä½åæ ·è¡¥0** ï¼ä¹å°±æ¯ä¸ç®¡æ¯æ£æ°è¿æ¯è´æ°ï¼å³ç§»é½ä¼å¨ç©ºç¼ºä½è¡¥ 0 ã
å¨å¾å° hash å¼åï¼å°±ä¼è¿è¡ put è¿ç¨ã
é¦å
ä¼å¤æ HashMap ä¸ç Node æ°ç»æ¯å¦ä¸º nullï¼å¦æç¬¬ä¸æ¬¡å建 HashMap å¹¶è¿è¡ç¬¬ä¸æ¬¡æå
¥å
ç´ ï¼é¦å
ä¼è¿è¡æ°ç»ç resizeï¼ä¹å°±æ¯`éæ°åé
`ï¼è¿éè¿æ¶åå°ä¸ä¸ª `resize()` æ©å®¹æºå¶æºç åæï¼æä»¬åé¢ä¼ä»ç»ãæ©å®¹å®æ¯åï¼ä¼è®¡ç®åº HashMap çåæ¾ä½ç½®ï¼éè¿ä½¿ç¨ **( n - 1 ) & hash** è¿è¡è®¡ç®å¾åºã

ç¶å伿è¿ä¸ªä½ç½®ä½ä¸ºæ°ç»ç䏿 ä½ä¸ºåæ¾å
ç´ çä½ç½®ã妿ä¸ä¸ºç©ºï¼é£ä¹è®¡ç®è¡¨ä¸çè¿ä¸ªçæ£çåå¸å¼ä¸è¦æå
¥ç key.hash ç¸æ¯ã妿åå¸å¼ç¸åï¼key-value ä¸ä¸æ ·ï¼å夿æ¯å¦æ¯æ çå®ä¾ï¼å¦ææ¯çè¯ï¼é£ä¹å°±æå®æå
¥å°æ ä¸ã妿䏿¯ï¼å°±æ§è¡å°¾ææ³å¨ entry é¾å°¾è¿è¡æå
¥ã

伿 ¹æ®æ¡¶ä¸å
ç´ çæ°é夿æ¯é¾è¡¨è¿æ¯çº¢é»æ ãç¶å夿é®å¼å¯¹æ°éæ¯å¦å¤§äºéå¼ï¼å¤§äºçè¯åè¿è¡æ©å®¹ã
### æ©å®¹æºå¶
å¨ Java ä¸ï¼æ°ç»çé¿åº¦æ¯åºå®çï¼è¿æå³çæ°ç»åªè½åå¨åºå®éçæ°æ®ãä½å¨å¼åçè¿ç¨ä¸ï¼å¾å¤æ¶åæä»¬æ æ³ç¥é该建å¤å¤§çæ°ç»åéãå¥½å¨ HashMap æ¯ä¸ç§èªå¨æ©å®¹çæ°æ®ç»æï¼å¨è¿ç§åºäºåé¿çæ°æ®ç»æä¸ï¼æ©å®¹æºå¶æ¯é常éè¦çã
å¨ HashMap ä¸ï¼éå¼å¤§å°ä¸ºæ¡¶æ°ç»é¿åº¦ä¸è´è½½å åçä¹ç§¯ãå½ HashMap ä¸çé®å¼å¯¹æ°éè¶
è¿é弿¶ï¼è¿è¡æ©å®¹ãHashMap ä¸çæ©å®¹æºå¶æ¯ç± `resize()` æ¹æ³æ¥å®ç°çï¼ä¸é¢æä»¬å°±æ¥ä¸æ¬¡è®¤è¯ä¸ãï¼è´´åºä¸ææ³¨éï¼ä¾¿äºå¤å¶ï¼
```java
final Node[] resize() {
Node[] oldTab = table;
// åå¨old table ç大å°
int oldCap = (oldTab == null) ? 0 : oldTab.length;
// å卿©å®¹éå¼
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
// 妿old tableæ°æ®å·²è¾¾æå¤§ï¼é£ä¹thresholdä¹è¢«è®¾ç½®ææå¤§
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
// 左移æ©å¤§äºå,
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
// æ©å®¹æåæ¥äºå
newThr = oldThr << 1; // double threshold
}
// 妿oldThr !> 0
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
// 妿old table <= 0 å¹¶ä¸ åå¨çéå¼ <= 0
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
// 妿æ©å
éå¼ä¸º0
if (newThr == 0) {
// æ©å®¹éå¼ä¸º åå§å®¹é*è´è½½å å
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
// éæ°ç»è´è½½å åèµå¼
threshold = newThr;
// è·åæ©å®¹åçæ°ç»
@SuppressWarnings({"rawtypes","unchecked"})
Node[] newTab = (Node[])new Node[newCap];
table = newTab;
// å¦æç¬¬ä¸æ¬¡è¿è¡table åå§åä¸ä¼èµ°ä¸é¢ç代ç
// æ©å®¹ä¹åéè¦éæ°æèç¹æ¾å¨æ°æ©å®¹çæ°ç»ä¸
if (oldTab != null) {
for (int j = 0; j < oldCap; ++j) {
Node e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
// éæ°æ å°æ¶ï¼éè¦å¯¹çº¢é»æ è¿è¡æå
((TreeNode)e).split(this, newTab, j, oldCap);
else { // preserve order
Node loHead = null, loTail = null;
Node hiHead = null, hiTail = null;
Node next;
// éåé¾è¡¨ï¼å¹¶å°é¾è¡¨èç¹æå顺åºè¿è¡åç»
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
// å°åç»åçé¾è¡¨æ å°å°æ°æ¡¶ä¸
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
```
æ©å®¹æºå¶æºç æ¯è¾é¿ï¼æä»¬èå¿ç¹è¿è¡æå
æä»¬ä»¥ if...else if...else é»è¾è¿è¡æåï¼ä¸é¢ä»£ç 主è¦åäºè¿å ä¸ªäºæ
* 夿 HashMap ä¸çæ°ç»çé¿åº¦ï¼ä¹å°±æ¯ `(Node[])oldTab.length()` ï¼å夿æ°ç»çé¿åº¦æ¯å¦æ¯æå¤§ççé¿åº¦ä¹å°±æ¯ 2^30 次å¹è¦å¤§ï¼å¤§çè¯ç´æ¥åæå¤§é¿åº¦ï¼å¦åå©ç¨ä½è¿ç® `<<`æ©å®¹ä¸ºåæ¥ç两å

* 妿æ°ç»é¿åº¦ä¸å¤§äº0 ï¼å夿æ©å®¹éå¼ `threshold` æ¯å¦å¤§äº 0 ï¼ä¹å°±æ¯çææ å¤é¨æå®çæ©å®¹éå¼ï¼è¥æå使ç¨ï¼è¿ééè¦è¯´æä¸ä¸ threshold 使¶æ¯ `oldThr > 0 `ï¼å 为 oldThr = threshold ï¼è¿éå
¶å®æ¯è¾çå°±æ¯ thresholdï¼å 为 HashMap ä¸çæ¯ä¸ªæé æ¹æ³é½ä¼è°ç¨ `HashMap(initCapacity,loadFactor)` è¿ä¸ªæé æ¹æ³ï¼æä»¥å¦ææ²¡æå¤é¨æå® initialCapacityï¼åå§å®¹é使ç¨çå°±æ¯ 16ï¼ç¶åæ ¹æ® `this.threshold = tableSizeFor(initialCapacity);` æ±å¾ threshold çå¼ã

* å¦åï¼ç´æ¥ä½¿ç¨é»è®¤çåå§å®¹é忩容éå¼ï¼èµ° else çé»è¾æ¯å¨ table åååå§åçæ¶åã

ç¶åä¼å¤æ newThr æ¯å¦ä¸º 0 ï¼ç¬è
å¨åå¼å§ç ç©¶æ¶åç° `newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);` ä¸ç´ä»¥ä¸ºè¿æ¯å¸¸éå乿³ï¼æä¹ä¼ä¸º 0 ï¼å
¶å®ä¸æ¯è¿é¨åçé®é¢ï¼å¨äºä¸é¢é»è¾å¤æä¸çæ©å®¹æä½ï¼å¯è½ä¼å¯¼è´`使º¢åº`ã
导è´ä½æº¢åºç示ä¾ï¼oldCap = 2^28 次å¹ï¼threshold > 2 ç䏿¬¡æ¹æ´æ°æ¬¡å¹ãå¨è¿å
¥å° `float ft = (float)newCap * loadFactor;` è¿ä¸ªæ¹æ³æ¯ 2^28 * 2^(3+n) ä¼ç´æ¥ > 2^31 次å¹ï¼å¯¼è´å
¨é¨å½é¶ã
**卿©å®¹åéè¦æèç¹æ¾å¨æ°æ©å®¹çæ°ç»ä¸ï¼è¿é乿¶åå°ä¸ä¸ªæ¥éª¤**
* å¾ªç¯æ¡¶ä¸çæ¯ä¸ª Node èç¹ï¼å¤æ Node[i] æ¯å¦ä¸ºç©ºï¼ä¸ºç©ºç´æ¥è¿åï¼ä¸ä¸ºç©ºåéåæ¡¶æ°ç»ï¼å¹¶å°é®å¼å¯¹æ å°å°æ°çæ¡¶æ°ç»ä¸ã
* 妿ä¸ä¸ºç©ºï¼å夿æ¯å¦æ¯æ å½¢ç»æï¼å¦ææ¯æ å½¢ç»æåæç
§æ å½¢ç»æè¿è¡æåï¼æåæ¹æ³å¨ `split` æ¹æ³ä¸ã
* 妿䏿¯æ å½¢ç»æï¼åéåé¾è¡¨ï¼å¹¶å°é¾è¡¨èç¹æå顺åºè¿è¡åç»ã

### 讲ä¸è®² get æ¹æ³å
¨è¿ç¨
æä»¬ä¸é¢è®²äº HashMap ä¸ç put æ¹æ³å
¨è¿ç¨ï¼ä¸é¢æä»¬æ¥çä¸ä¸ `get` æ¹æ³çè¿ç¨ï¼
```java
public V get(Object key) {
Node e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
final Node getNode(int hash, Object key) {
Node[] tab; Node first, e; int n; K k;
// æ¾å°çå®çå
ç´ ä½ç½®
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
// æ»æ¯ä¼check ä¸ä¸ç¬¬ä¸ä¸ªå
ç´
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
// 妿䏿¯ç¬¬ä¸ä¸ªå
ç´ ï¼å¹¶ä¸ä¸ä¸ä¸ªå
ç´ ä¸æ¯ç©ºç
if ((e = first.next) != null) {
// 夿æ¯å¦å±äº TreeNodeï¼å¦ææ¯ TreeNode å®ä¾ï¼ç´æ¥ä» TreeNode.getTreeNode å
if (first instanceof TreeNode)
return ((TreeNode)first).getTreeNode(hash, key);
// 妿è¿ä¸æ¯ TreeNode å®ä¾ï¼å°±ç´æ¥å¾ªç¯æ°ç»å
ç´ ï¼ç´å°æ¾å°æå®å
ç´ ä½ç½®
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
```
æ¥ç®åä»ç»ä¸å§ï¼é¦å
伿£æ¥ table ä¸çå
ç´ æ¯å¦ä¸ºç©ºï¼ç¶åæ ¹æ® hash ç®åºæå® key çä½ç½®ãç¶åæ£æ¥é¾è¡¨ç第ä¸ä¸ªå
ç´ æ¯å¦ä¸ºç©ºï¼å¦æä¸ä¸ºç©ºï¼æ¯å¦å¹é
ï¼å¦æå¹é
ï¼ç´æ¥è¿åè¿æ¡è®°å½ï¼å¦æå¹é
ï¼å夿ä¸ä¸ä¸ªå
ç´ ç弿¯å¦ä¸º nullï¼ä¸ºç©ºç´æ¥è¿åï¼å¦æä¸ä¸ºç©ºï¼å夿æ¯å¦æ¯ `TreeNode` å®ä¾ï¼å¦ææ¯ TreeNode å®ä¾ï¼åç´æ¥ä½¿ç¨ `TreeNode.getTreeNode` ååºå
ç´ ï¼å¦åæ§è¡å¾ªç¯ï¼ç´å°ä¸ä¸ä¸ªå
ç´ ä¸º null ä½ç½®ã
`getNode` æ¹æ³æä¸ä¸ªæ¯è¾éè¦çè¿ç¨å°±æ¯ **(n - 1) & hash**ï¼è¿æ®µä»£ç æ¯ç¡®å®éè¦æ¥æ¾çæ¡¶çä½ç½®çï¼é£ä¹ï¼ä¸ºä»ä¹è¦ (n - 1) & hash å¢ï¼
n å°±æ¯ HashMap 䏿¡¶çæ°éï¼è¿å¥è¯çææä¹å°±æ¯è¯´ (n - 1) & hash å°±æ¯ (æ¡¶ç容é - 1) & hash
```java
// 为ä»ä¹ HashMap çæ£ç´¢ä½ç½®æ¯ (table.size - 1) & hash
public static void main(String[] args) {
Map map = new HashMap<>();
// debug å¾ç¥ 1 ç hash å¼ç®åºæ¥æ¯ 49
map.put("1","cxuan");
// debug å¾ç¥ 1 ç hash å¼ç®åºæ¥æ¯ 50
map.put("2","cxuan");
// debug å¾ç¥ 1 ç hash å¼ç®åºæ¥æ¯ 51
map.put("3","cxuan");
}
```
é£ä¹æ¯æ¬¡ç®å®ä¹åç (n - 1) & hash ï¼ä¾æ¬¡ä¸º

ä¹å°±æ¯ **tab[(n - 1) & hash]** ç®åºçå
·ä½ä½ç½®ã
### HashMap çéåæ¹å¼
HashMap çéåï¼ä¹æ¯ä¸ä¸ªä½¿ç¨é¢æ¬¡ç¹å«é«çæä½
HashMap éåçåºç±»æ¯ `HashIterator`ï¼å®æ¯ä¸ä¸ª Hash è¿ä»£å¨ï¼å®æ¯ä¸ä¸ª HashMap å
é¨çæ½è±¡ç±»ï¼å®çæé æ¯è¾ç®åï¼åªæä¸ç§æ¹æ³ï¼**hasNext ã remove å nextNode** æ¹æ³ï¼å
¶ä¸ nextNode æ¹æ³æ¯ç±ä¸ç§è¿ä»£å¨å®ç°ç
è¿ä¸ç§è¿ä»£å¨å°±å°±æ¯
* `KeyIterator` ï¼å¯¹ key è¿è¡éå
* `ValueIterator`ï¼å¯¹ value è¿è¡éå
* `EntryIterator`ï¼ å¯¹ Entry é¾è¿è¡éå
è½ç¶è¯´ççè¿ä»£å¨æ¯è¾å¤ï¼ä½å
¶å®ä»ä»¬çéå顺åºé½æ¯ä¸æ ·çï¼æé ä¹é常ç®åï¼é½æ¯ä½¿ç¨ `HashIterator` ä¸ç `nextNode` æ¹æ³è¿è¡éå
```java
final class KeyIterator extends HashIterator
implements Iterator {
public final K next() { return nextNode().key; }
}
final class ValueIterator extends HashIterator
implements Iterator {
public final V next() { return nextNode().value; }
}
final class EntryIterator extends HashIterator
implements Iterator> {
public final Map.Entry next() { return nextNode(); }
}
```
HashIterator ä¸çéåæ¹å¼
```java
abstract class HashIterator {
Node next; // ä¸ä¸ä¸ª entry èç¹
Node current; // å½å entry èç¹
int expectedModCount; // fail-fast ç夿æ è¯
int index; // å½åæ§½
HashIterator() {
expectedModCount = modCount;
Node[] t = table;
current = next = null;
index = 0;
if (t != null && size > 0) { // advance to first entry
do {} while (index < t.length && (next = t[index++]) == null);
}
}
public final boolean hasNext() {
return next != null;
}
final Node nextNode() {
Node[] t;
Node e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {} while (index < t.length && (next = t[index++]) == null);
}
return e;
}
public final void remove() {...}
}
```
next å current åå«è¡¨ç¤ºä¸ä¸ä¸ª Node èç¹åå½åç Node èç¹ï¼HashIterator å¨åå§åæ¶ä¼éåææçèç¹ãä¸é¢æä»¬ç¨å¾æ¥è¡¨ç¤ºä¸ä¸ä»ä»¬çéå顺åº

ä½ ä¼åç° `nextNode()` æ¹æ³çéåæ¹å¼å HashIterator çéåæ¹å¼ä¸æ ·ï¼åªä¸è¿å¤ææ¡ä»¶ä¸ä¸æ ·ï¼æé HashIterator çæ¶å夿æ¡ä»¶æ¯ææ²¡æé¾è¡¨ï¼æ¡¶æ¯å¦ä¸º nullï¼èéå nextNode ç夿æ¡ä»¶å为ä¸ä¸ä¸ª node èç¹æ¯ä¸æ¯ null ï¼å¹¶ä¸æ¡¶æ¯ä¸æ¯ä¸º nullã
### HashMap ä¸çç§»é¤æ¹æ³
HashMap ä¸çç§»é¤æ¹æ³ä¹æ¯è¾ç®åäºï¼æºç å¦ä¸
```java
public V remove(Object key) {
Node e;
return (e = removeNode(hash(key), key, null, false, true)) == null ?
null : e.value;
}
final Node removeNode(int hash, Object key, Object value,
boolean matchValue, boolean movable) {
Node[] tab; Node p; int n, index;
if ((tab = table) != null && (n = tab.length) > 0 &&
(p = tab[index = (n - 1) & hash]) != null) {
Node node = null, e; K k; V v;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
node = p;
else if ((e = p.next) != null) {
if (p instanceof TreeNode)
node = ((TreeNode)p).getTreeNode(hash, key);
else {
do {
if (e.hash == hash &&
((k = e.key) == key ||
(key != null && key.equals(k)))) {
node = e;
break;
}
p = e;
} while ((e = e.next) != null);
}
}
if (node != null && (!matchValue || (v = node.value) == value ||
(value != null && value.equals(v)))) {
if (node instanceof TreeNode)
((TreeNode)node).removeTreeNode(this, tab, movable);
else if (node == p)
tab[index] = node.next;
else
p.next = node.next;
++modCount;
--size;
afterNodeRemoval(node);
return node;
}
}
return null;
}
```
remove æ¹æ³æå¾å¤ï¼æç»é½ä¼è°ç¨å° removeNode æ¹æ³ï¼åªä¸è¿ä¼ éçåæ°å¼ä¸åï¼æä»¬æ¿ remove(object) æ¥æ¼ç¤ºä¸ä¸ã
é¦å
ä¼éè¿ hash æ¥æ¾å°å¯¹åºç bucketï¼ç¶åéè¿éåé¾è¡¨ï¼æ¾å°é®å¼ç¸ççèç¹ï¼ç¶åæå¯¹åºçèç¹è¿è¡å é¤ã
## å
³äº HashMap çé¢è¯é¢
### HashMap çæ°æ®ç»æ
JDK1.7 ä¸ï¼HashMap éç¨`使¡¶ + é¾è¡¨`çå®ç°ï¼å³ä½¿ç¨`é¾è¡¨`æ¥å¤çå²çªï¼åä¸ hash å¼çé¾è¡¨é½åå¨å¨ä¸ä¸ªæ°ç»ä¸ã使¯å½ä½äºä¸ä¸ªæ¡¶ä¸çå
ç´ è¾å¤ï¼å³ hash å¼ç¸ççå
ç´ è¾å¤æ¶ï¼éè¿ key å¼ä¾æ¬¡æ¥æ¾çæçè¾ä½ã
æä»¥ï¼ä¸ JDK 1.7 ç¸æ¯ï¼JDK 1.8 å¨åºå±ç»ææ¹é¢åäºä¸äºæ¹åï¼å½æ¯ä¸ªæ¡¶ä¸å
ç´ å¤§äº 8 çæ¶åï¼ä¼è½¬åä¸ºçº¢é»æ ï¼ç®çå°±æ¯ä¼åæ¥è¯¢æçã
### HashMap ç put è¿ç¨
大è´è¿ç¨å¦ä¸ï¼é¦å
ä¼ä½¿ç¨ hash æ¹æ³è®¡ç®å¯¹è±¡çåå¸ç ï¼æ ¹æ®åå¸ç æ¥ç¡®å®å¨ bucket ä¸åæ¾çä½ç½®ï¼å¦æ bucket 䏿²¡æ Node èç¹åç´æ¥è¿è¡ putï¼å¦æå¯¹åº bucket å·²ç»æ Node èç¹ï¼ä¼å¯¹é¾è¡¨é¿åº¦è¿è¡åæï¼å¤æé¿åº¦æ¯å¦å¤§äº 8ï¼å¦æé¾è¡¨é¿åº¦å°äº 8 ï¼å¨ JDK1.7 åä¼ä½¿ç¨å¤´ææ³ï¼å¨ JDK1.8 ä¹åæ´æ¹ä¸ºå°¾ææ³ã妿é¾è¡¨é¿åº¦å¤§äº 8 ä¼è¿è¡æ åæä½ï¼æé¾è¡¨è½¬æ¢ä¸ºçº¢é»æ ï¼å¨çº¢é»æ ä¸è¿è¡åå¨ã
### HashMap 为å¥çº¿ç¨ä¸å®å
¨
HashMap 䏿¯ä¸ä¸ªçº¿ç¨å®å
¨ç容å¨ï¼ä¸å®å
¨æ§ä½ç°å¨å¤çº¿ç¨å¹¶å对 HashMap è¿è¡ put æä½ä¸ã妿æä¸¤ä¸ªçº¿ç¨ A å B ï¼é¦å
A 叿æå
¥ä¸ä¸ªé®å¼å¯¹å° HashMap ä¸ï¼å¨å³å®å¥½æ¡¶çä½ç½®è¿è¡ put æ¶ï¼æ¤æ¶ A çæ¶é´çæ£å¥½ç¨å®äºï¼è½®å° B è¿è¡ï¼B è¿è¡åæ§è¡å A 䏿 ·çæä½ï¼åªä¸è¿ B æåæé®å¼å¯¹æå
¥è¿å»äºã妿 A å B æå
¥çä½ç½®ï¼æ¡¶ï¼æ¯ä¸æ ·çï¼é£ä¹çº¿ç¨ A ç»§ç»æ§è¡åå°±ä¼è¦ç B çè®°å½ï¼é æäºæ°æ®ä¸ä¸è´é®é¢ã
è¿æä¸ç¹å¨äº HashMap 卿©å®¹æ¶ï¼å resize æ¹æ³ä¼å½¢æç¯ï¼é ææ»å¾ªç¯ï¼å¯¼è´ CPU é£é«ã
### HashMap æ¯å¦ä½å¤çåå¸ç¢°æç
HashMap åºå±æ¯ä½¿ç¨ä½æ¡¶ + é¾è¡¨å®ç°çï¼ä½æ¡¶å³å®å
ç´ çæå
¥ä½ç½®ï¼ä½æ¡¶æ¯ç± hash æ¹æ³å³å®çï¼å½å¤ä¸ªå
ç´ ç hash 计ç®å¾å°ç¸åçåå¸å¼åï¼HashMap 伿å¤ä¸ª Node å
ç´ é½æ¾å¨å¯¹åºç使¡¶ä¸ï¼å½¢æé¾è¡¨ï¼è¿ç§å¤çåå¸ç¢°æçæ¹å¼è¢«ç§°ä¸ºé¾å°åæ³ã
å
¶ä»å¤ç hash 碰æçæ¹å¼è¿æ **弿¾å°åæ³ãrehash æ¹æ³ã建ç«ä¸ä¸ªå
Œ
±æº¢åºåº**è¿å ç§æ¹æ³ã
### HashMap æ¯å¦ä½ get å
ç´ ç
é¦å
伿£æ¥ table ä¸çå
ç´ æ¯å¦ä¸ºç©ºï¼ç¶åæ ¹æ® hash ç®åºæå® key çä½ç½®ãç¶åæ£æ¥é¾è¡¨ç第ä¸ä¸ªå
ç´ æ¯å¦ä¸ºç©ºï¼å¦æä¸ä¸ºç©ºï¼æ¯å¦å¹é
ï¼å¦æå¹é
ï¼ç´æ¥è¿åè¿æ¡è®°å½ï¼å¦æå¹é
ï¼å夿ä¸ä¸ä¸ªå
ç´ ç弿¯å¦ä¸º nullï¼ä¸ºç©ºç´æ¥è¿åï¼å¦æä¸ä¸ºç©ºï¼å夿æ¯å¦æ¯ `TreeNode` å®ä¾ï¼å¦ææ¯ TreeNode å®ä¾ï¼åç´æ¥ä½¿ç¨ `TreeNode.getTreeNode` ååºå
ç´ ï¼å¦åæ§è¡å¾ªç¯ï¼ç´å°ä¸ä¸ä¸ªå
ç´ ä¸º null ä½ç½®ã
### HashMap å HashTable æä»ä¹åºå«
è§ä¸
### HashMap å HashSet çåºå«
è§ä¸
### HashMap æ¯å¦ä½æ©å®¹ç
HashMap ä¸æä¸¤ä¸ªé常éè¦çåéï¼ä¸ä¸ªæ¯ `loadFactor` ï¼ä¸ä¸ªæ¯ `threshold` ï¼loadFactor 表示çå°±æ¯è´è½½å åï¼threshold è¡¨ç¤ºçæ¯ä¸ä¸æ¬¡è¦æ©å®¹çéå¼ï¼å½ threshold = loadFactor * æ°ç»é¿åº¦æ¶ï¼æ°ç»é¿åº¦æ©å¤§ä½åæ¥ç两åï¼æ¥éæ°è°æ´ map ç大å°ï¼å¹¶å°åæ¥ç对象æ¾å
¥æ°ç bucket æ°ç»ä¸ã
### HashMap çé¿åº¦ä¸ºä»ä¹æ¯ 2 ç广¬¡æ¹
è¿é颿æ³äºå 天ï¼ä¹åå群éå°ä¼ä¼´ä»¬æ¢è®¨æ¯æ¥ä¸é¢çæ¶åï¼é®ä»ä»¬ä¸ºä»ä¹ length%hash == (n - 1) & hashï¼å®ä»¬è¯´ç¸ççåææ¯ length çé¿åº¦ 2 ç广¬¡æ¹ï¼ç¶åæåäºä¸å¥é¾é length è¿è½ä¸æ¯ 2 ç广¬¡æ¹åï¼å
¶å®æ¯ææ²¡æææå æå
³ç³»ï¼å 为 HashMap çé¿åº¦æ¯ 2 ç广¬¡æ¹ï¼æä»¥ä½¿ç¨ä½æ°æ¥å¤æå¨æ¡¶ä¸ç䏿 ã妿 length çé¿åº¦ä¸æ¯ 2 ç广¬¡æ¹ï¼å°ä¼ä¼´ä»¬å¯ä»¥ä¸¾ä¸ªä¾åæ¥è¯è¯
>ä¾å¦é¿åº¦ä¸º 9 æ¶åï¼3 & (9-1) = 0ï¼2 & (9-1) = 0 ï¼é½å¨ 0 ä¸ï¼ç¢°æäºï¼
è¿æ ·ä¼å¢å¤§ HashMap 碰æçå çã
### HashMap 线ç¨å®å
¨çå®ç°æåªäº
å 为 HashMap 䏿¯ä¸ä¸ªçº¿ç¨å®å
¨ç容å¨ï¼æä»¥å¹¶ååºæ¯ä¸æ¨èä½¿ç¨ `ConcurrentHashMap` ï¼æè
使ç¨çº¿ç¨å®å
¨ç HashMapï¼ä½¿ç¨ `Collections` å
ä¸ç线ç¨å®å
¨ç容å¨ï¼æ¯å¦è¯´
```java
Collections.synchronizedMap(new HashMap());
```
è¿å¯ä»¥ä½¿ç¨ HashTable ï¼å®ä¹æ¯çº¿ç¨å®å
¨ç容å¨ï¼åºäº key-value åå¨ï¼ç»å¸¸ç¨ HashMap å HashTable 忝è¾å°±æ¯å 为 HashTable çæ°æ®ç»æå HashMap ç¸åã
ä¸é¢æçæé«çå°±æ¯ ConcurrentHashMapã
## åè®°
æç« 并没æå述太å¤å
³äºçº¢é»æ çæé ãå
嫿·»å ãå é¤ãæ åçè¿ç¨ï¼ä¸æ¹é¢æ¯èªå·±è½åè¿è¾¾ä¸å°ï¼ä¸æ¹é¢æ¯å
³äºçº¢é»æ çæè¿°å¤ªè¿äºå æ®ç¯å¹
ï¼çº¢é»æ 忝å¾å¤§çä¸é¨åå
å®¹ï¼æä»¥ä¼èèæ¾å¨åé¢ççº¢é»æ è¿è¡è®²è§£ã
å¦æä½ å¨é
读æç« çè¿ç¨ä¸åç°é误åé®é¢ï¼è¯·åæ¶ä¸æèç³»ï¼
妿æç« å¯¹ä½ æå¸®å©ï¼å¸æå°ä¼ä¼´ä»¬ä¸è¿èµ°èµ·ï¼