前言
HashMap一直是我的一個心病,因爲在面試的時候HashMap是個出現頻率高發點,不管是知識點,還是現場編程,而且自己當時答得不好,今天就回歸到源碼,真正探究下HashMap的底層實現,去獲知它的特性。
特性描述
(1)基於哈希表的 Map 接口的實現。此實現提供所有可選的映射操作,並允許使用 null 值和 null 鍵。(除了非同步和允許使用 null 之外,HashMap 類與 Hashtable 大致相同。)此類不保證映射的順序,特別是它不保證該順序恆久不變。
(2)此實現假定哈希函數將元素適當地分佈在各桶之間,可爲基本操作(get 和 put)提供穩定的性能。迭代 collection 視圖所需的時間與 HashMap 實例的“容量”(桶的數量)及其大小(鍵-值映射關係數)成比例。所以,如果迭代性能很重要,則不要將初始容量設置得太高(或將加載因子設置得太低)。
(3)HashMap 的實例有兩個參數影響其性能:初始容量 和加載因子。容量 是哈希表中桶的數量,初始容量只是哈希表在創建時的容量。加載因子 是哈希表在其容量自動增加之前可以達到多滿的一種尺度。當哈希表中的條目數超出了加載因子與當前容量的乘積時,則要對該哈希表進行 rehash 操作(即重建內部數據結構),從而哈希表將具有大約兩倍的桶數。
通常,默認加載因子 (.75) 在時間和空間成本上尋求一種折衷。加載因子過高雖然減少了空間開銷,但同時也增加了查詢成本(在大多數 HashMap 類的操作中,包括 get 和 put 操作,都反映了這一點)。在設置初始容量時應該考慮到映射中所需的條目數及其加載因子,以便最大限度地減少 rehash 操作次數。如果初始容量大於最大條目數除以加載因子,則不會發生 rehash 操作。
如果很多映射關係要存儲在 HashMap 實例中,則相對於按需執行自動的 rehash 操作以增大表的容量來說,使用足夠大的初始容量創建它將使得映射關係能更有效地存儲。
(4)注意,此實現不是同步的。如果多個線程同時訪問一個哈希映射,而其中至少一個線程從結構上修改了該映射,則它必須 保持外部同步。(結構上的修改是指添加或刪除一個或多個映射關係的任何操作;僅改變與實例已經包含的鍵關聯的值不是結構上的修改。)這一般通過對自然封裝該映射的對象進行同步操作來完成。如果不存在這樣的對象,則應該使用 Collections.synchronizedMap 方法來“包裝”該映射。最好在創建時完成這一操作,以防止對映射進行意外的非同步訪問,如下所示:
Map m = Collections.synchronizedMap(new HashMap(…));由所有此類的“collection 視圖方法”所返回的迭代器都是快速失敗 的:在迭代器創建之後,如果從結構上對映射進行修改,除非通過迭代器本身的 remove 方法,其他任何時間任何方式的修改,迭代器都將拋出 ConcurrentModificationException。因此,面對併發的修改,迭代器很快就會完全失敗,而不冒在將來不確定的時間發生任意不確定行爲的風險。
注意,迭代器的快速失敗行爲不能得到保證,一般來說,存在非同步的併發修改時,不可能作出任何堅決的保證。快速失敗迭代器盡最大努力拋出 ConcurrentModificationException。因此,編寫依賴於此異常的程序的做法是錯誤的,正確做法是:迭代器的快速失敗行爲應該僅用於檢測程序錯誤。
描述
上面這些基本都是JDK中對HashMap的描述,下面這段描述是我對於HashMap的理解,如果有錯誤還望指正,謝謝!
(1)HashMap的內部存儲結構其實是數組和鏈表的結合。當實例化一個HashMap時,系統會創建一個長度爲Capacity的Entry數組,這個長度被稱爲容量(Capacity),在這個數組中可以存放元素的位置我們稱之爲“桶”(bucket),每個bucket都有自己的索引,系統可以根據索引快速的查找bucket中的元素。
每個bucket中存儲一個元素,即一個Entry對象,但每一個Entry對象可以帶一個引用變量,用於指向下一個元素,因此,在一個桶中,就有可能生成一個Entry鏈。
(2) 在存儲一對值時(Key—->Value對),實際上是存儲在一個Entry的對象e中,程序通過key計算出Entry對象的存儲位置。換句話說,Key—->Value的對應關係是通過key—-Entry—-value這個過程實現的,所以就有我們表面上知道的key存在哪裏,value就存在哪裏。
(3)HashMap的衝突處理是用的是鏈地址法, 將所有哈希地址相同的記錄都鏈接在同一鏈表中。也就是說,當HashMap中的每一個bucket裏只有一個Entry,不發生衝突時,Hashmap是一個數組,根據索引可以迅速找到Entry,但是,當發生衝突時,單個的bucket裏存儲的是一個Entry鏈,系統必須按順序遍歷每個Entry,直到找到爲止。爲了減少數據的遍歷,衝突的元素都是直接插入到第一個Entry後面的,所以,最早放入bucket中的Entry,位於Entry鏈中的最末端。這從put(K key,V value)中也可以看出,在同一個bucket存儲Entry鏈的情況下,新放入的Entry總是位於bucket中。
(4)對於Map接口來說,其本身是不能直接使用迭代(Iteraor)進行輸出的,因爲Map接口的中的每個位置存放的是一對值(key—->value),而Iterator中每次只能找到一個值,如果要通過迭代的方法進行輸出,主要分爲以下幾步:
1、將Map接口的實例通過Set entrySet();方法變爲Set接口對象;
2、通過Set接口實例爲Iterator實例化
3、通過Iterator迭代輸出,輸出的每個內容都是Map.Entry的對象
4、通過Map.Entry進行key—value的分離
源碼
//繼承了AbstractMap抽象類,實現了Map接口
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
{
//默認初始化化容量,即16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//最大容量,即2的30次方
static final int MAXIMUM_CAPACITY = 1 << 30;
//默認裝載因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//HashMap內部的存儲結構是一個數組,此處數組爲空,即沒有初始化之前的狀態
static final Entry<?,?>[] EMPTY_TABLE = {};
//空的存儲實體
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
//HashMap的元素數目
transient int size;
//HashMap下次擴容是的閥值
int threshold;
//HashMap的裝載因子
final float loadFactor;
//修改次數
transient int modCount;
//默認的threshold值
static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
//通過虛擬機配置來修改threshold值
private static class Holder {
static final int ALTERNATIVE_HASHING_THRESHOLD;
static {
String altThreshold = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(
"jdk.map.althashing.threshold"));//讀取配置值
int threshold;
try {
threshold = (null != altThreshold)//修改threshold值
? Integer.parseInt(altThreshold)
: ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
if (threshold == -1) {
threshold = Integer.MAX_VALUE;
}
if (threshold < 0) {
throw new IllegalArgumentException("value must be positive integer.");
}
} catch(IllegalArgumentException failed) {
throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
}
ALTERNATIVE_HASHING_THRESHOLD = threshold;
}
}
//計算Hash值時的key
transient int hashSeed = 0;
//通過初始容量和狀態因子構造HashMap
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 = initialCapacity;
init();//這個實現爲空
}
//通過擴容因子構造HashMap,容量去默認值,即16
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
//裝載因子取0.75,容量取16,構造HashMap
public HashMap() {
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}
//通過其他Map來初始化HashMap,容量通過其他Map的size來計算,裝載因子取0.75
public HashMap(Map<? extends K, ? extends V> m) {
this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
inflateTable(threshold);//初始化HashMap底層的數組結構
putAllForCreate(m);//添加m中的元素
}
//選擇合適的容量值,容量值取大於等於最接近number的2的冪數
private static int roundUpToPowerOf2(int number) {
int rounded = number >= MAXIMUM_CAPACITY //參數有效性檢查
? MAXIMUM_CAPACITY
: (rounded = Integer.highestOneBit(number)) != 0
? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded
: 1;
return rounded;
}
//初始化HashMap的底層數據結構
private void inflateTable(int toSize) {
int capacity = roundUpToPowerOf2(toSize);//選取合適的容量值
threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);//選取合適的threshold(擴容閥值)
table = new Entry[capacity];//初始化底層數據結構
initHashSeedAsNeeded(capacity);//選擇合適的Hash因子
}
//目前爲空
void init() {
}
//選擇合適的Hash因子,這裏和虛擬機的配置有關
final boolean initHashSeedAsNeeded(int capacity) {
boolean currentAltHashing = hashSeed != 0;
boolean useAltHashing = sun.misc.VM.isBooted() &&
(capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
boolean switching = currentAltHashing ^ useAltHashing;
if (switching) {
hashSeed = useAltHashing
? sun.misc.Hashing.randomHashSeed(this)
: 0;
}
return switching;
}
//計算key的Hash值,這裏針對String類的Key優化了Hash函數
final int hash(Object k) {
int h = hashSeed;
if (0 != h && k instanceof String) {//這裏針對String優化了Hash函數,是否使用新的Hash函數和Hash因子有關
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
//根據Hash值和Hash表的大小選擇合適的Hash桶
static int indexFor(int h, int length) {
return h & (length-1);
}
//返回HashMap的元素個數
public int size() {
return size;
}
//判斷是否爲空
public boolean isEmpty() {
return size == 0;
}
//獲取key值爲key的元素值
public V get(Object key) {
if (key == null)//如果Key值爲空,則獲取對應的值,這裏也可以看到,HashMap允許null的key,其內部針對null的key有特殊的邏輯
return getForNullKey();
Entry<K,V> entry = getEntry(key);//獲取實體
return null == entry ? null : entry.getValue();//判斷是否爲空,不爲空,則獲取對應的值
}
//獲取key爲null的實體
private V getForNullKey() {
if (size == 0) {//如果元素個數爲0,則直接返回null
return null;
}
//key爲null的元素存儲在table的第0個位置
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null)//判斷是否爲null
return e.value;//返回其值
}
return null;
}
//判斷是否有鍵爲key的元素
public boolean containsKey(Object key) {
return getEntry(key) != null;//這裏需要遍歷
}
//獲取鍵值爲key的元素
final Entry<K,V> getEntry(Object key) {
if (size == 0) {//元素個數爲0
return null;//直接返回null
}
int hash = (key == null) ? 0 : hash(key);//獲取key的Hash值
for (Entry<K,V> e = table[indexFor(hash, table.length)];//根據key和表的長度,定位到Hash桶
e != null;
e = e.next) {//進行遍歷
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))//判斷Hash值和對應的key,合適則返回值
return e;
}
return null;
}
//添加元素
public V put(K key, V value) {
if (table == EMPTY_TABLE) {//如果底層表爲空,則初始化
inflateTable(threshold);
}
if (key == null)//如果key爲空,則執行空的邏輯
return putForNullKey(value);
int hash = hash(key);//獲取key的Hash值
int i = indexFor(hash, table.length);//定位Hash桶
for (Entry<K,V> 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);//調用value的回調函數,其實這個函數也爲空實現
return oldValue;
}
}
modCount++;//更新修改次數
addEntry(hash, key, value, i);//添加到對應Hash桶的鏈接表中
return null;
}
//添加key爲空的元素,key爲null的元素添加到第0號Hash桶中
private V putForNullKey(V value) {
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null) {//判斷元素
V oldValue = e.value;//如果已經存在,修改值
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;//更新修改次數
addEntry(0, null, value, 0);//執行鏈表插入
return null;
}
//添加元素
private void putForCreate(K key, V value) {
int hash = null == key ? 0 : hash(key);//計算key的Hash值
int i = indexFor(hash, table.length);//定位Hash桶
//遍歷第i號Hash桶
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
e.value = value;
return;
}
}
//創建元素實體,這裏會添加到第i號Hash桶中
createEntry(hash, key, value, i);
}
//添加m中的元素到HashMap中
private void putAllForCreate(Map<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())//遍歷添加
putForCreate(e.getKey(), e.getValue());
}
//按新的容量擴容Hash表
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, initHashSeedAsNeeded(newCapacity));//將老的表中的數據拷貝到新的結構中
table = newTable;//修改HashMap的底層數組
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);//修改閥值
}
//將老的表中的數據拷貝到新的結構中
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;//容量
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {//如果是重新Hash,則需要重新計算hash值
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);//定位Hash桶
e.next = newTable[i];//元素連接到桶中,這裏相當於單鏈表的插入
newTable[i] = e;
e = next;
}
}
}
//添加元素
public void putAll(Map<? extends K, ? extends V> m) {
int numKeysToBeAdded = m.size();
if (numKeysToBeAdded == 0)//m爲空,則直接返回
return;
if (table == EMPTY_TABLE) {//底層數組爲空
inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold));//執行初始化
}
//按m的size執行HashMap的擴容
if (numKeysToBeAdded > threshold) {//閥值代表的擴容的條件,如果比閥值要大,則一定要擴容
int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);//選擇容量值
if (targetCapacity > MAXIMUM_CAPACITY)//有效性判斷
targetCapacity = MAXIMUM_CAPACITY;
int newCapacity = table.length;//目前的容量
while (newCapacity < targetCapacity)//如果小於m的容量,則增加目前的容量
newCapacity <<= 1;
if (newCapacity > table.length)
resize(newCapacity);//執行擴容
}
//有足夠的空間之後進行擴容
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
put(e.getKey(), e.getValue());//執行添加操作
}
//刪除元素,元素的鍵值爲key
public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key);//刪除鍵爲key的元素
return (e == null ? null : e.value);//同時返回該值
}
//刪除元素,元素的鍵值爲key
final Entry<K,V> removeEntryForKey(Object key) {
if (size == 0) {
return null;
}
int hash = (key == null) ? 0 : hash(key);//計算Hash值
int i = indexFor(hash, table.length);//定位Hash桶
Entry<K,V> prev = table[i];
Entry<K,V> e = prev;//保存前面一個指針值
while (e != null) {
Entry<K,V> next = e.next;
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {//在Hash桶中定位元素
modCount++;//更新修改次數
size--;//元素個數-1
if (prev == e)//是否是第一個元素
table[i] = next;
else
prev.next = next;//執行的是單鏈表的刪除
e.recordRemoval(this);
return e;
}
prev = e;//單鏈表移動指針
e = next;
}
return e;
}
//刪除一個Entry實體,這裏通過o的key查找到元素,之後刪除,和上面的實現類似
final Entry<K,V> removeMapping(Object o) {
if (size == 0 || !(o instanceof Map.Entry))//參數有效性驗證
return null;
Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
Object key = entry.getKey();
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
Entry<K,V> prev = table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && e.equals(entry)) {
modCount++;
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
return e;
}
prev = e;
e = next;
}
return e;
}
//清空Hash表
public void clear() {
modCount++;//更新修改次數
Arrays.fill(table, null);//底層數組置爲null
size = 0;//元素個數爲0
}
//判斷是否包含值爲value的元素
public boolean containsValue(Object value) {
if (value == null)//值爲null
return containsNullValue();//執行null的邏輯
Entry[] tab = table;
//執行兩層循環來查找
for (int i = 0; i < tab.length ; i++)
for (Entry e = tab[i] ; e != null ; e = e.next)
if (value.equals(e.value))//這裏判斷內容
return true;
return false;
}
//執行null的邏輯
private boolean containsNullValue() {
Entry[] tab = table;
for (int i = 0; i < tab.length ; i++)
for (Entry e = tab[i] ; e != null ; e = e.next)
if (e.value == null)//這裏直接判斷引用
return true;
return false;
}
//淺複製HashMap
public Object clone() {
HashMap<K,V> result = null;
try {
result = (HashMap<K,V>)super.clone();
} catch (CloneNotSupportedException e) {
// assert false;
}
if (result.table != EMPTY_TABLE) {
result.inflateTable(Math.min(
(int) Math.min(
size * Math.min(1 / loadFactor, 4.0f),
// we have limits...
HashMap.MAXIMUM_CAPACITY),
table.length));
}
result.entrySet = null;
result.modCount = 0;
result.size = 0;
result.init();
result.putAllForCreate(this);
return result;
}
//實現Map.Entry接口,這是HashMap內部key和value的一個抽象
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;//鍵
V value;//值
Entry<K,V> next;//指向下一個元素的指針
int hash;//key的hash值
//創建Entry
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
//判斷元素內容
public final boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry)o;
Object k1 = getKey();
Object k2 = e.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {//判斷鍵
Object v1 = getValue();
Object v2 = e.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2)))//判斷值
return true;
}
return false;
}
public final int hashCode() {
return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());//鍵和值的hash值的異或
}
public final String toString() {
return getKey() + "=" + getValue();
}
//空實現
void recordAccess(HashMap<K,V> m) {
}
//空實現
void recordRemoval(HashMap<K,V> m) {
}
}
//添加Entry
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {//判斷是否需要擴容
resize(2 * table.length);//按2倍擴容
hash = (null != key) ? hash(key) : 0;//計算hash值
bucketIndex = indexFor(hash, table.length);//定位Hash桶
}
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++;//元素個數+1
}
//繼承了Iterator接口,提供迭代器實現
private abstract class HashIterator<E> implements Iterator<E> {
Entry<K,V> next; //下一個實體
int expectedModCount; //迭代器修改次數
int index; //Hash桶的索引號
Entry<K,V> current; //當前實體
HashIterator() {
expectedModCount = modCount;//更新修改次數
if (size > 0) { //目前有元素
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)//尋找第一個不爲空的Hash桶
;
}
}
//判斷是否有下一個元素
public final boolean hasNext() {
return next != null;
}
//返回下一個元素
final Entry<K,V> nextEntry() {
if (modCount != expectedModCount)//迭代期間有修改,則拋出異常
throw new ConcurrentModificationException();
Entry<K,V> e = next;//從next開始遍歷
if (e == null)
throw new NoSuchElementException();
if ((next = e.next) == null) {//如果爲空,則找到下一個不爲空的Hash桶
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
current = e;//返回next的值
return e;
}
//刪除元素
public void remove() {
if (current == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Object k = current.key;
current = null;
HashMap.this.removeEntryForKey(k);//調用父類刪除元素
expectedModCount = modCount;//修改併發修改次數
}
}
//HashMap值集迭代器,依賴Entry迭代器
private final class ValueIterator extends HashIterator<V> {
public V next() {
return nextEntry().value;
}
}
//HashMap鍵集迭代器,依賴Entry迭代器
private final class KeyIterator extends HashIterator<K> {
public K next() {
return nextEntry().getKey();
}
}
//HashMap Entry迭代器
private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() {
return nextEntry();
}
}
//返回鍵集迭代器
Iterator<K> newKeyIterator() {
return new KeyIterator();
}
//返回值集迭代器
Iterator<V> newValueIterator() {
return new ValueIterator();
}
//返回Entry迭代器
Iterator<Map.Entry<K,V>> newEntryIterator() {
return new EntryIterator();
}
//視圖結合,HashMap內部Entry的集合
private transient Set<Map.Entry<K,V>> entrySet = null;
//返回鍵集
public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
}
//鍵集合的實現,實現了AbstractSet抽象類,調用了父類的方法
private final class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return newKeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void clear() {
HashMap.this.clear();
}
}
//返回值集合
public Collection<V> values() {
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
}
//值集合的實現,實現了AbstractCollection抽象類,調用了父類的方法來實現
private final class Values extends AbstractCollection<V> {
public Iterator<V> iterator() {
return newValueIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsValue(o);
}
public void clear() {
HashMap.this.clear();
}
}
//entry集合
public Set<Map.Entry<K,V>> entrySet() {
return entrySet0();
}
//防火entry集合
private Set<Map.Entry<K,V>> entrySet0() {
Set<Map.Entry<K,V>> es = entrySet;
return es != null ? es : (entrySet = new EntrySet());
}
//entry集合的實現,繼承了AbstractSet抽象類
private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator<Map.Entry<K,V>> iterator() {//迭代器的實現
return newEntryIterator();
}
public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<K,V> e = (Map.Entry<K,V>) o;
Entry<K,V> candidate = getEntry(e.getKey());
return candidate != null && candidate.equals(e);
}
public boolean remove(Object o) {
return removeMapping(o) != null;
}
public int size() {
return size;
}
public void clear() {
HashMap.this.clear();
}
}
//序列化和反序列化的實現
}