1、前言數組
在遍歷HashMap與LinkedHashMap時,咱們一般都會使用到迭代器,而HashMap的迭代器與LinkedHashMap迭代器是如何工做的呢?下面咱們來一塊兒分析分析。ide
2、迭代器繼承圖函數
3、HashMap迭代器源碼分析
3.1 HashIterator學習
HashIterator是一個抽象類,封裝了迭代器內部工做的一些操做。spa
HashIterator類屬性3d
abstract class HashIterator { // 下一個結點 Node<K,V> next; // next entry to return // 當前結點 Node<K,V> current; // current entry // 指望的修改次數 int expectedModCount; // for fast-fail // 當前桶索引 int index; // current slot }
說明:其中expectedModCount屬性主要用於在遍歷HashMap同時,程序對其結構是否進行了修改。若遍歷同時修改了,則會拋出異常。code
HashIterator構造函數 blog
HashIterator() { // 成員變量賦值 expectedModCount = modCount; Node<K,V>[] t = table; current = next = null; index = 0; // table不爲空而且大小大於0 if (t != null && size > 0) { // advance to first entry // 找到table數組中第一個存在的結點,即找到第一個具備元素的桶 do {} while (index < t.length && (next = t[index++]) == null); } }
說明:next將表示第一個非空桶中的第一個結點,index將表示下一個桶。繼承
HashIterator核心函數分析
1. hasNext函數
// 是否存在下一個結點 public final boolean hasNext() { return next != null; }
2. nextNode函數
final Node<K,V> nextNode() { // 記錄next結點 Node<K,V> e = next; // 若在遍歷時對HashMap進行結構性的修改則會拋出異常 if (modCount != expectedModCount) throw new ConcurrentModificationException(); // 下一個結點爲空,拋出異常 if (e == null) throw new NoSuchElementException(); // 若是下一個結點爲空,而且table表不爲空;表示桶中全部結點已經遍歷完,需尋找下一個不爲空的桶 if ((next = (current = e).next) == null && (t = table) != null) { // 找到下一個不爲空的桶 do {} while (index < t.length && (next = t[index++]) == null); } return e; }
說明:nextNode函數屏蔽掉了桶的不一樣所帶來的差別,就好像全部元素在同一個桶中,依次進行遍歷。
3. remove函數
public final void remove() { Node<K,V> p = current; // 當前結點爲空,拋出異常 if (p == null) throw new IllegalStateException(); // 若在遍歷時對HashMap進行結構性的修改則會拋出異常 if (modCount != expectedModCount) throw new ConcurrentModificationException(); // 當前結點爲空 current = null; K key = p.key; // 移除結點 removeNode(hash(key), key, null, false, false); // 賦最新值 expectedModCount = modCount; }
3.2 KeyIterator
KeyIterator類是鍵迭代器,繼承自HashIterator,實現了Iterator接口,能夠對HashMap中的鍵進行遍歷。
類定義
final class KeyIterator extends HashIterator implements Iterator<K> { public final K next() { return nextNode().key; } }
3.3 ValueIterator
ValueIterator類是值迭代器,繼承自HashIterator,實現了Iterator接口,與KeyIterator相似,對值進行遍歷。
final class ValueIterator extends HashIterator implements Iterator<V> { public final V next() { return nextNode().value; } }
3.4 EntryIterator
EntryIterator類是結點迭代器,繼承自HashIterator,實現了Iterator接口,與KeyIterator、ValueIterator相似,對結點進行遍歷。
final class ValueIterator extends HashIterator implements Iterator<V> { public final V next() { return nextNode().value; } }
4、LinkedHashMap迭代器
4.1 LinkedHashIterator
LinkedHashIterator是LinkedHashMap的迭代器,爲抽象類,用於對LinkedHashMap進行迭代。
LinkedHashIterator類屬性
abstract class LinkedHashIterator { // 下一個結點 LinkedHashMap.Entry<K,V> next; // 當前結點 LinkedHashMap.Entry<K,V> current; // 指望的修改次數 int expectedModCount; }
LinkedHashIterator構造函數
LinkedHashIterator() { // next賦值爲頭結點 next = head; // 賦值修改次數 expectedModCount = modCount; // 當前結點賦值爲空 current = null; }
LinkedHashIterator核心函數
hasNext函數
// 是否存在下一個結點 public final boolean hasNext() { return next != null; }
nextNode函數
final LinkedHashMap.Entry<K,V> nextNode() { LinkedHashMap.Entry<K,V> e = next; // 檢查是否存在結構性修改 if (modCount != expectedModCount) throw new ConcurrentModificationException(); // 當前結點是否爲空 if (e == null) throw new NoSuchElementException(); // 賦值當前節點 current = e; // 賦值下一個結點 next = e.after; return e; }
說明:因爲全部的結點構成雙鏈表結構,因此nextNode函數也很好理解,直接取得下一個結點便可。
public final void remove() { // 保存當前結點 Node<K,V> p = current; if (p == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); current = null; K key = p.key; // 移除結點 removeNode(hash(key), key, null, false, false); // 更新最新修改數 expectedModCount = modCount; }
4.2 LinkedKeyIterator
LinkedHashMap的鍵迭代器,繼承自LinkedHashIterator,實現了Iterator接口,對LinkedHashMap中的鍵進行迭代。
final class LinkedKeyIterator extends LinkedHashIterator implements Iterator<K> { public final K next() { return nextNode().getKey(); } }
4.3 LinkedValueIterator
LinkedHashMap的值迭代器,繼承自LinkedHashIterator,實現了Iterator接口,對LinkedHashMap中的值進行迭代。
final class LinkedValueIterator extends LinkedHashIterator implements Iterator<V> { public final V next() { return nextNode().value; } }
4.4 LinkedEntryIterator
LinkedHashMap的結點迭代器,繼承自LinkedHashIterator,實現了Iterator接口,對LinkedHashMap中的結點進行迭代。
final class LinkedEntryIterator extends LinkedHashIterator implements Iterator<Map.Entry<K,V>> { public final Map.Entry<K,V> next() { return nextNode(); } }
5、總結
HashMap迭代器與LinkedHashMap迭代器有不少類似的地方,對比進行學習效果更佳。迭代器要屏蔽掉底層的細節,提供統一的接口供用戶訪問。HashMap與LinkedHashMap的迭代器源碼分析就到此爲止,仍是很簡單的,謝謝各位園友觀看~