---
title: HashMap æºç åæ
category: Java
tag:
- Javaéå
---
> æè°¢ [changfubai](https://github.com/changfubai) å¯¹æ¬æçæ¹è¿ååºçè´¡ç®ï¼
## HashMap ç®ä»
HashMap 主è¦ç¨æ¥åæ¾é®å¼å¯¹ï¼å®åºäºåå¸è¡¨ç Map æ¥å£å®ç°ï¼æ¯å¸¸ç¨ç Java éåä¹ä¸ï¼æ¯é线ç¨å®å
¨çã
`HashMap` å¯ä»¥åå¨ null ç key å valueï¼ä½ null ä½ä¸ºé®åªè½æä¸ä¸ªï¼null ä½ä¸ºå¼å¯ä»¥æå¤ä¸ª
JDK1.8 ä¹å HashMap ç± æ°ç»+é¾è¡¨ ç»æçï¼æ°ç»æ¯ HashMap ç主ä½ï¼é¾è¡¨åæ¯ä¸»è¦ä¸ºäºè§£å³åå¸å²çªèåå¨çï¼âæé¾æ³âè§£å³å²çªï¼ã JDK1.8 以åç `HashMap` å¨è§£å³åå¸å²çªæ¶æäºè¾å¤§çååï¼å½é¾è¡¨é¿åº¦å¤§äºçäºéå¼ï¼é»è®¤ä¸º 8ï¼ï¼å°é¾è¡¨è½¬æ¢æçº¢é»æ åä¼å¤æï¼å¦æå½åæ°ç»çé¿åº¦å°äº 64ï¼é£ä¹ä¼éæ©å
è¿è¡æ°ç»æ©å®¹ï¼è䏿¯è½¬æ¢ä¸ºçº¢é»æ ï¼æ¶ï¼å°é¾è¡¨è½¬åä¸ºçº¢é»æ ï¼ä»¥åå°æç´¢æ¶é´ã
`HashMap` é»è®¤çåå§å大å°ä¸º 16ãä¹åæ¯æ¬¡æ©å
ï¼å®¹éåä¸ºåæ¥ç 2 åãå¹¶ä¸ï¼ `HashMap` æ»æ¯ä½¿ç¨ 2 çå¹ä½ä¸ºåå¸è¡¨ç大å°ã
## åºå±æ°æ®ç»æåæ
### JDK1.8 ä¹å
JDK1.8 ä¹å HashMap åºå±æ¯ **æ°ç»åé¾è¡¨** ç»åå¨ä¸èµ·ä½¿ç¨ä¹å°±æ¯ **é¾è¡¨æ£å**ã
HashMap éè¿ key ç hashCode ç»è¿æ°å¨å½æ°å¤çè¿åå¾å° hash å¼ï¼ç¶åéè¿ `(n - 1) & hash` 夿å½åå
ç´ åæ¾çä½ç½®ï¼è¿éç n æçæ¯æ°ç»çé¿åº¦ï¼ï¼å¦æå½åä½ç½®åå¨å
ç´ çè¯ï¼å°±å¤æè¯¥å
ç´ ä¸è¦åå
¥çå
ç´ ç hash å¼ä»¥å key æ¯å¦ç¸åï¼å¦æç¸åçè¯ï¼ç´æ¥è¦çï¼ä¸ç¸åå°±éè¿æé¾æ³è§£å³å²çªã
æè°æ°å¨å½æ°æçå°±æ¯ HashMap ç hash æ¹æ³ãä½¿ç¨ hash æ¹æ³ä¹å°±æ¯æ°å¨å½æ°æ¯ä¸ºäºé²æ¢ä¸äºå®ç°æ¯è¾å·®ç hashCode() æ¹æ³ æ¢å¥è¯è¯´ä½¿ç¨æ°å¨å½æ°ä¹åå¯ä»¥åå°ç¢°æã
**JDK 1.8 HashMap ç hash æ¹æ³æºç :**
JDK 1.8 ç hash æ¹æ³ ç¸æ¯äº JDK 1.7 hash æ¹æ³æ´å ç®åï¼ä½æ¯åçä¸åã
```java
static final int hash(Object key) {
int h;
// key.hashCode()ï¼è¿åæ£åå¼ä¹å°±æ¯hashcode
// ^ï¼æä½å¼æ
// >>>:æ 符å·å³ç§»ï¼å¿½ç¥ç¬¦å·ä½ï¼ç©ºä½é½ä»¥0è¡¥é½
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
```
对æ¯ä¸ä¸ JDK1.7 ç HashMap ç hash æ¹æ³æºç .
```java
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);
}
```
ç¸æ¯äº JDK1.8 ç hash æ¹æ³ ï¼JDK 1.7 ç hash æ¹æ³çæ§è½ä¼ç¨å·®ä¸ç¹ç¹ï¼å 为æ¯ç«æ°å¨äº 4 次ã
æè° **âæé¾æ³â** å°±æ¯ï¼å°é¾è¡¨åæ°ç»ç¸ç»åãä¹å°±æ¯è¯´å建ä¸ä¸ªé¾è¡¨æ°ç»ï¼æ°ç»ä¸æ¯ä¸æ ¼å°±æ¯ä¸ä¸ªé¾è¡¨ãè¥éå°åå¸å²çªï¼åå°å²çªçå¼å å°é¾è¡¨ä¸å³å¯ã

### JDK1.8 ä¹å
ç¸æ¯äºä¹åççæ¬ï¼JDK1.8 以åå¨è§£å³åå¸å²çªæ¶æäºè¾å¤§çååã
å½é¾è¡¨é¿åº¦å¤§äºéå¼ï¼é»è®¤ä¸º 8ï¼æ¶ï¼ä¼é¦å
è°ç¨ `treeifyBin()`æ¹æ³ãè¿ä¸ªæ¹æ³ä¼æ ¹æ® HashMap æ°ç»æ¥å³å®æ¯å¦è½¬æ¢ä¸ºçº¢é»æ ãåªæå½æ°ç»é¿åº¦å¤§äºæè
çäº 64 çæ
åµä¸ï¼æä¼æ§è¡è½¬æ¢çº¢é»æ æä½ï¼ä»¥åå°æç´¢æ¶é´ãå¦åï¼å°±æ¯åªæ¯æ§è¡ `resize()` æ¹æ³å¯¹æ°ç»æ©å®¹ãç¸å
³æºç è¿éå°±ä¸è´´äºï¼éç¹å
³æ³¨ `treeifyBin()`æ¹æ³å³å¯ï¼

**ç±»ç屿§ï¼**
```java
public class HashMap extends AbstractMap implements Map, Cloneable, Serializable {
// åºåå·
private static final long serialVersionUID = 362498820763181265L;
// é»è®¤çåå§å®¹éæ¯16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
// æå¤§å®¹é
static final int MAXIMUM_CAPACITY = 1 << 30;
// é»è®¤çè´è½½å å
static final float DEFAULT_LOAD_FACTOR = 0.75f;
// 彿¡¶(bucket)ä¸çç»ç¹æ°å¤§äºçäºè¿ä¸ªå¼æ¶ä¼è½¬æçº¢é»æ
static final int TREEIFY_THRESHOLD = 8;
// 彿¡¶(bucket)ä¸çç»ç¹æ°å°äºçäºè¿ä¸ªå¼æ¶æ 转é¾è¡¨
static final int UNTREEIFY_THRESHOLD = 6;
// æ¡¶ä¸ç»æè½¬åä¸ºçº¢é»æ 对åºçtableçæå°å®¹é
static final int MIN_TREEIFY_CAPACITY = 64;
// åå¨å
ç´ çæ°ç»ï¼æ»æ¯2ç广¬¡å
transient Node[] table;
// ä¸ä¸ªå
å«äºæ å°ä¸ææé®å¼å¯¹çéåè§å¾
transient Set> entrySet;
// åæ¾å
ç´ ç个æ°ï¼æ³¨æè¿ä¸ªä¸çäºæ°ç»çé¿åº¦ã
transient int size;
// æ¯æ¬¡æ©å®¹åæ´æ¹mapç»æç计æ°å¨
transient int modCount;
// éå¼(容é*è´è½½å å) å½å®é
大å°è¶
è¿é弿¶ï¼ä¼è¿è¡æ©å®¹
int threshold;
// è´è½½å å
final float loadFactor;
}
```
- **loadFactor è´è½½å å**
loadFactor è´è½½å 忝æ§å¶æ°ç»åæ¾æ°æ®ççå¯ç¨åº¦ï¼loadFactor è¶è¶è¿äº 1ï¼é£ä¹ æ°ç»ä¸åæ¾çæ°æ®(entry)ä¹å°±è¶å¤ï¼ä¹å°±è¶å¯ï¼ä¹å°±æ¯ä¼è®©é¾è¡¨çé¿åº¦å¢å ï¼loadFactor è¶å°ï¼ä¹å°±æ¯è¶è¿äº 0ï¼æ°ç»ä¸åæ¾çæ°æ®(entry)ä¹å°±è¶å°ï¼ä¹å°±è¶ç¨çã
**loadFactor å¤ªå¤§å¯¼è´æ¥æ¾å
ç´ æçä½ï¼å¤ªå°å¯¼è´æ°ç»çå©ç¨çä½ï¼åæ¾çæ°æ®ä¼å¾åæ£ãloadFactor çé»è®¤å¼ä¸º 0.75f æ¯å®æ¹ç»åºçä¸ä¸ªæ¯è¾å¥½ç临çå¼**ã
ç»å®çé»è®¤å®¹é为 16ï¼è´è½½å å为 0.75ãMap å¨ä½¿ç¨è¿ç¨ä¸ä¸æçå¾éé¢åæ¾æ°æ®ï¼å½æ°éè¶
è¿äº 16 \* 0.75 = 12 å°±éè¦å°å½å 16 ç容éè¿è¡æ©å®¹ï¼èæ©å®¹è¿ä¸ªè¿ç¨æ¶åå° rehashãå¤å¶æ°æ®çæä½ï¼æä»¥é常æ¶èæ§è½ã
- **threshold**
**threshold = capacity \* loadFactor**ï¼**å½ Size>threshold**çæ¶åï¼é£ä¹å°±è¦èè对æ°ç»çæ©å¢äºï¼ä¹å°±æ¯è¯´ï¼è¿ä¸ªçææå°±æ¯ **è¡¡éæ°ç»æ¯å¦éè¦æ©å¢çä¸ä¸ªæ å**ã
**Node èç¹ç±»æºç :**
```java
// ç»§æ¿èª Map.Entry
static class Node implements Map.Entry {
final int hash;// åå¸å¼ï¼åæ¾å
ç´ å°hashmap䏿¶ç¨æ¥ä¸å
¶ä»å
ç´ hash弿¯è¾
final K key;//é®
V value;//å¼
// æåä¸ä¸ä¸ªèç¹
Node next;
Node(int hash, K key, V value, Node next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
// éåhashCode()æ¹æ³
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
// éå equals() æ¹æ³
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry,?> e = (Map.Entry,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
```
**æ èç¹ç±»æºç :**
```java
static final class TreeNode extends LinkedHashMap.Entry {
TreeNode parent; // ç¶
TreeNode left; // å·¦
TreeNode right; // å³
TreeNode prev; // needed to unlink next upon deletion
boolean red; // 夿é¢è²
TreeNode(int hash, K key, V val, Node next) {
super(hash, key, val, next);
}
// è¿åæ ¹èç¹
final TreeNode root() {
for (TreeNode r = this, p;;) {
if ((p = r.parent) == null)
return r;
r = p;
}
```
## HashMap æºç åæ
### æé æ¹æ³
HashMap 䏿å个æé æ¹æ³ï¼å®ä»¬åå«å¦ä¸ï¼
```java
// é»è®¤æé 彿°ã
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
// å
å«å¦ä¸ä¸ªâMapâçæé 彿°
public HashMap(Map extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);//ä¸é¢ä¼åæå°è¿ä¸ªæ¹æ³
}
// æå®â容é大å°âçæé 彿°
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
// æå®â容é大å°âåâè´è½½å åâçæé 彿°
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;
// åå§å®¹éææ¶åæ¾å° threshold ï¼å¨resizeä¸åèµå¼ç» newCap è¿è¡tableåå§å
this.threshold = tableSizeFor(initialCapacity);
}
```
> å¼å¾æ³¨æçæ¯ä¸è¿°å个æé æ¹æ³ä¸ï¼é½åå§åäºè´è½½å å loadFactorï¼ç±äº HashMap 䏿²¡æ capacity è¿æ ·çåæ®µï¼å³ä½¿æå®äºåå§å容é initialCapacity ï¼ä¹åªæ¯éè¿ tableSizeFor å°å
¶æ©å®¹å°ä¸ initialCapacity ææ¥è¿ç 2 ç广¬¡æ¹å¤§å°ï¼ç¶åææ¶èµå¼ç» threshold ï¼åç»éè¿ resize æ¹æ³å° threshold èµå¼ç» newCap è¿è¡ table çåå§åã
**putMapEntries æ¹æ³ï¼**
```java
final void putMapEntries(Map extends K, ? extends V> m, boolean evict) {
int s = m.size();
if (s > 0) {
// 夿tableæ¯å¦å·²ç»åå§å
if (table == null) { // pre-size
/*
* æªåå§åï¼s为mçå®é
å
ç´ ä¸ªæ°ï¼ft=s/loadFactor => s=ft*loadFactor, è·æä»¬å颿å°ç
* éå¼=容é*è´è½½å å æ¯ä¸æ¯å¾åï¼æ¯çï¼ftæçæ¯è¦æ·»å s个å
ç´ æéçæå°ç容é
*/
float ft = ((float)s / loadFactor) + 1.0F;
int t = ((ft < (float)MAXIMUM_CAPACITY) ?
(int)ft : MAXIMUM_CAPACITY);
/*
* æ ¹æ®æé 彿°å¯ç¥ï¼tableæªåå§åï¼thresholdå®é
䏿¯åæ¾çåå§å容éï¼å¦ææ·»å s个å
ç´ æ
* éçæå°å®¹é大äºåå§å容éï¼åå°æå°å®¹éæ©å®¹ä¸ºææ¥è¿ç2ç广¬¡æ¹å¤§å°ä½ä¸ºåå§åã
* 注æè¿é䏿¯åå§åéå¼
*/
if (t > threshold)
threshold = tableSizeFor(t);
}
// å·²åå§åï¼å¹¶ä¸må
ç´ ä¸ªæ°å¤§äºéå¼ï¼è¿è¡æ©å®¹å¤ç
else if (s > threshold)
resize();
// å°mä¸çææå
ç´ æ·»å è³HashMapä¸ï¼å¦ætableæªåå§åï¼putValä¸ä¼è°ç¨resizeåå§åææ©å®¹
for (Map.Entry extends K, ? extends V> e : m.entrySet()) {
K key = e.getKey();
V value = e.getValue();
putVal(hash(key), key, value, false, evict);
}
}
}
```
### put æ¹æ³
HashMap åªæä¾äº put ç¨äºæ·»å å
ç´ ï¼putVal æ¹æ³åªæ¯ç» put æ¹æ³è°ç¨çä¸ä¸ªæ¹æ³ï¼å¹¶æ²¡ææä¾ç»ç¨æ·ä½¿ç¨ã
**对 putVal æ¹æ³æ·»å å
ç´ çåæå¦ä¸ï¼**
1. 妿å®ä½å°çæ°ç»ä½ç½®æ²¡æå
ç´ å°±ç´æ¥æå
¥ã
2. 妿å®ä½å°çæ°ç»ä½ç½®æå
ç´ å°±åè¦æå
¥ç key æ¯è¾ï¼å¦æ key ç¸åå°±ç´æ¥è¦çï¼å¦æ key ä¸ç¸åï¼å°±å¤æ p æ¯å¦æ¯ä¸ä¸ªæ èç¹ï¼å¦ææ¯å°±è°ç¨`e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value)`å°å
ç´ æ·»å è¿å
¥ã妿䏿¯å°±éåé¾è¡¨æå
¥(æå
¥çæ¯é¾è¡¨å°¾é¨)ã

```java
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node[] tab; Node p; int n, i;
// tableæªåå§åæè
é¿åº¦ä¸º0ï¼è¿è¡æ©å®¹
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// (n - 1) & hash ç¡®å®å
ç´ åæ¾å¨åªä¸ªæ¡¶ä¸ï¼æ¡¶ä¸ºç©ºï¼æ°çæç»ç¹æ¾å
¥æ¡¶ä¸(æ¤æ¶ï¼è¿ä¸ªç»ç¹æ¯æ¾å¨æ°ç»ä¸)
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
// æ¡¶ä¸å·²ç»åå¨å
ç´ ï¼å¤çhashå²çªï¼
else {
Node e; K k;
//å¿«éå¤æç¬¬ä¸ä¸ªèç¹table[i]çkeyæ¯å¦ä¸æå
¥çkey䏿 ·ï¼è¥ç¸åå°±ç´æ¥ä½¿ç¨æå
¥çå¼pæ¿æ¢ææ§çå¼eã
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
// 夿æå
¥çæ¯å¦æ¯çº¢é»æ èç¹
else if (p instanceof TreeNode)
// æ¾å
¥æ ä¸
e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
// 䏿¯çº¢é»æ èç¹å说æä¸ºé¾è¡¨ç»ç¹
else {
// å¨é¾è¡¨ææ«æå
¥ç»ç¹
for (int binCount = 0; ; ++binCount) {
// å°è¾¾é¾è¡¨çå°¾é¨
if ((e = p.next) == null) {
// å¨å°¾é¨æå
¥æ°ç»ç¹
p.next = newNode(hash, key, value, null);
// ç»ç¹æ°éè¾¾å°éå¼(é»è®¤ä¸º 8 )ï¼æ§è¡ treeifyBin æ¹æ³
// è¿ä¸ªæ¹æ³ä¼æ ¹æ® HashMap æ°ç»æ¥å³å®æ¯å¦è½¬æ¢ä¸ºçº¢é»æ ã
// åªæå½æ°ç»é¿åº¦å¤§äºæè
çäº 64 çæ
åµä¸ï¼æä¼æ§è¡è½¬æ¢çº¢é»æ æä½ï¼ä»¥åå°æç´¢æ¶é´ãå¦åï¼å°±æ¯åªæ¯å¯¹æ°ç»æ©å®¹ã
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
// è·³åºå¾ªç¯
break;
}
// 夿é¾è¡¨ä¸ç»ç¹çkeyå¼ä¸æå
¥çå
ç´ çkey弿¯å¦ç¸ç
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
// ç¸çï¼è·³åºå¾ªç¯
break;
// ç¨äºéåæ¡¶ä¸çé¾è¡¨ï¼ä¸åé¢çe = p.nextç»åï¼å¯ä»¥éåé¾è¡¨
p = e;
}
}
// è¡¨ç¤ºå¨æ¡¶ä¸æ¾å°keyå¼ãhashå¼ä¸æå
¥å
ç´ ç¸ççç»ç¹
if (e != null) {
// è®°å½eçvalue
V oldValue = e.value;
// onlyIfAbsent为falseæè
æ§å¼ä¸ºnull
if (!onlyIfAbsent || oldValue == null)
//ç¨æ°å¼æ¿æ¢æ§å¼
e.value = value;
// 访é®ååè°
afterNodeAccess(e);
// è¿åæ§å¼
return oldValue;
}
}
// ç»ææ§ä¿®æ¹
++modCount;
// å®é
大å°å¤§äºéå¼åæ©å®¹
if (++size > threshold)
resize();
// æå
¥ååè°
afterNodeInsertion(evict);
return null;
}
```
**æä»¬åæ¥å¯¹æ¯ä¸ä¸ JDK1.7 put æ¹æ³ç代ç **
**å¯¹äº put æ¹æ³çåæå¦ä¸ï¼**
- â 妿å®ä½å°çæ°ç»ä½ç½®æ²¡æå
ç´ å°±ç´æ¥æå
¥ã
- â¡ å¦æå®ä½å°çæ°ç»ä½ç½®æå
ç´ ï¼éå以è¿ä¸ªå
ç´ ä¸ºå¤´ç»ç¹çé¾è¡¨ï¼ä¾æ¬¡åæå
¥ç key æ¯è¾ï¼å¦æ key ç¸åå°±ç´æ¥è¦çï¼ä¸åå°±éç¨å¤´ææ³æå
¥å
ç´ ã
```java
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 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;
}
```
### 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) {
// æ°ç»å
ç´ ç¸ç
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
// æ¡¶ä¸ä¸æ¢ä¸ä¸ªèç¹
if ((e = first.next) != null) {
// 卿 ä¸get
if (first instanceof TreeNode)
return ((TreeNode)first).getTreeNode(hash, key);
// å¨é¾è¡¨ä¸get
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
```
### resize æ¹æ³
è¿è¡æ©å®¹ï¼ä¼ä¼´éç䏿¬¡éæ° hash åé
ï¼å¹¶ä¸ä¼éå hash è¡¨ä¸ææçå
ç´ ï¼æ¯éå¸¸èæ¶çãå¨ç¼åç¨åºä¸ï¼è¦å°½éé¿å
resizeãresize æ¹æ³å®é
䏿¯å° table åå§åå table æ©å®¹ è¿è¡äºæ´åï¼åºå±çè¡ä¸ºé½æ¯ç» table èµå¼ä¸ä¸ªæ°çæ°ç»ã
```java
final Node[] resize() {
Node[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
// è¶
è¿æå¤§å¼å°±ä¸åæ©å
äºï¼å°±åªå¥½éä½ ç¢°æå»å§
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
// 没è¶
è¿æå¤§å¼ï¼å°±æ©å
ä¸ºåæ¥ç2å
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // double threshold
}
else if (oldThr > 0) // initial capacity was placed in threshold
// å建对象æ¶åå§å容é大尿¾å¨thresholdä¸ï¼æ¤æ¶åªéè¦å°å
¶ä½ä¸ºæ°çæ°ç»å®¹é
newCap = oldThr;
else {
// signifies using defaults æ åæé 彿°å建ç对象å¨è¿é计ç®å®¹éåéå¼
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) {
// åå»ºæ¶æå®äºåå§å容éæè
è´è½½å åï¼å¨è¿éè¿è¡éå¼åå§åï¼
// æè
æ©å®¹åçæ§å®¹éå°äº16ï¼å¨è¿éè®¡ç®æ°çresizeä¸é
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;
if (oldTab != null) {
// ææ¯ä¸ªbucketé½ç§»å¨å°æ°çbucketsä¸
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)
// å°çº¢é»æ æåæ2æ£µåæ ï¼å¦æåæ èç¹æ°å°äºçäº UNTREEIFY_THRESHOLDï¼é»è®¤ä¸º 6ï¼ï¼åå°åæ 转æ¢ä¸ºé¾è¡¨ã
// å¦æåæ èç¹æ°å¤§äº UNTREEIFY_THRESHOLDï¼åä¿æåæ çæ ç»æã
((TreeNode)e).split(this, newTab, j, oldCap);
else {
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;
}
// åç´¢å¼+oldCap
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
// åç´¢å¼æ¾å°bucketé
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
// åç´¢å¼+oldCapæ¾å°bucketé
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
```
## HashMap å¸¸ç¨æ¹æ³æµè¯
```java
package map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
public class HashMapDemo {
public static void main(String[] args) {
HashMap map = new HashMap();
// é®ä¸è½éå¤ï¼å¼å¯ä»¥éå¤
map.put("san", "å¼ ä¸");
map.put("si", "æå");
map.put("wu", "çäº");
map.put("wang", "èç");
map.put("wang", "èç2");// èç被è¦ç
map.put("lao", "èç");
System.out.println("-------ç´æ¥è¾åºhashmap:-------");
System.out.println(map);
/**
* éåHashMap
*/
// 1.è·åMapä¸çææé®
System.out.println("-------foreachè·åMap䏿æçé®:------");
Set keys = map.keySet();
for (String key : keys) {
System.out.print(key+" ");
}
System.out.println();//æ¢è¡
// 2.è·åMap䏿æå¼
System.out.println("-------foreachè·åMap䏿æçå¼:------");
Collection values = map.values();
for (String value : values) {
System.out.print(value+" ");
}
System.out.println();//æ¢è¡
// 3.å¾å°keyçå¼çåæ¶å¾å°keyæå¯¹åºçå¼
System.out.println("-------å¾å°keyçå¼çåæ¶å¾å°keyæå¯¹åºçå¼:-------");
Set keys2 = map.keySet();
for (String key : keys2) {
System.out.print(key + "ï¼" + map.get(key)+" ");
}
/**
* 妿æ¢è¦éåkeyåè¦valueï¼é£ä¹å»ºè®®è¿ç§æ¹å¼ï¼å ä¸ºå¦æå
è·åkeySetç¶ååæ§è¡map.get(key)ï¼mapå
é¨ä¼æ§è¡ä¸¤æ¬¡éåã
* 䏿¬¡æ¯å¨è·åkeySetçæ¶åï¼ä¸æ¬¡æ¯å¨éåæækeyçæ¶åã
*/
// 彿è°ç¨put(key,value)æ¹æ³çæ¶åï¼é¦å
伿keyåvalueå°è£
å°
// Entryè¿ä¸ªéæå
é¨ç±»å¯¹è±¡ä¸ï¼æEntryå¯¹è±¡åæ·»å å°æ°ç»ä¸ï¼æä»¥æä»¬æ³è·å
// mapä¸çææé®å¼å¯¹ï¼æä»¬åªè¦è·åæ°ç»ä¸çææEntryå¯¹è±¡ï¼æ¥ä¸æ¥
// è°ç¨Entry对象ä¸çgetKey()ågetValue()æ¹æ³å°±è½è·åé®å¼å¯¹äº
Set> entrys = map.entrySet();
for (java.util.Map.Entry entry : entrys) {
System.out.println(entry.getKey() + "--" + entry.getValue());
}
/**
* HashMapå
¶ä»å¸¸ç¨æ¹æ³
*/
System.out.println("after map.size()ï¼"+map.size());
System.out.println("after map.isEmpty()ï¼"+map.isEmpty());
System.out.println(map.remove("san"));
System.out.println("after map.remove()ï¼"+map);
System.out.println("after map.get(si)ï¼"+map.get("si"));
System.out.println("after map.containsKey(si)ï¼"+map.containsKey("si"));
System.out.println("after containsValue(æå)ï¼"+map.containsValue("æå"));
System.out.println(map.replace("si", "æå2"));
System.out.println("after map.replace(si, æå2):"+map);
}
}
```