【集合框架】JDK1.8源碼分析之HashMap & LinkedHashMap迭代器(三)

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
}
View Code

  說明:其中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);
        }
    }
View Code

  說明:next將表示第一個非空桶中的第一個結點,index將表示下一個桶。繼承

  HashIterator核心函數分析

  1. hasNext函數

// 是否存在下一個結點
public final boolean hasNext() {
    return next != null; 
}
View Code

  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;
}
View Code

  說明: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;
}
View Code

  3.2 KeyIterator

  KeyIterator類是鍵迭代器,繼承自HashIterator,實現了Iterator接口,能夠對HashMap中的鍵進行遍歷。

  類定義 

final class KeyIterator extends HashIterator
    implements Iterator<K> {
    public final K next() { return nextNode().key; }
}
View Code

  3.3 ValueIterator

  ValueIterator類是值迭代器,繼承自HashIterator,實現了Iterator接口,與KeyIterator相似,對值進行遍歷。  

final class ValueIterator extends HashIterator
    implements Iterator<V> {
    public final V next() { return nextNode().value; }
}
View Code

  3.4 EntryIterator

  EntryIterator類是結點迭代器,繼承自HashIterator,實現了Iterator接口,與KeyIterator、ValueIterator相似,對結點進行遍歷。 

final class ValueIterator extends HashIterator
    implements Iterator<V> {
    public final V next() { return nextNode().value; }
}
View Code

4、LinkedHashMap迭代器

  4.1 LinkedHashIterator

  LinkedHashIterator是LinkedHashMap的迭代器,爲抽象類,用於對LinkedHashMap進行迭代。 

  LinkedHashIterator類屬性

abstract class LinkedHashIterator {
    // 下一個結點
    LinkedHashMap.Entry<K,V> next;
    // 當前結點
    LinkedHashMap.Entry<K,V> current;
    // 指望的修改次數
    int expectedModCount;
}
View Code

  LinkedHashIterator構造函數  

LinkedHashIterator() {
    // next賦值爲頭結點
    next = head;
    // 賦值修改次數
    expectedModCount = modCount;
    // 當前結點賦值爲空
    current = null;
}
View Code

  LinkedHashIterator核心函數

  hasNext函數

// 是否存在下一個結點
public final boolean hasNext() {
    return next != null;
}
View Code

  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;
}
View Code

  說明:因爲全部的結點構成雙鏈表結構,因此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;
}
View Code

  4.2 LinkedKeyIterator

  LinkedHashMap的鍵迭代器,繼承自LinkedHashIterator,實現了Iterator接口,對LinkedHashMap中的鍵進行迭代。 

final class LinkedKeyIterator extends LinkedHashIterator
    implements Iterator<K> {
    public final K next() { return nextNode().getKey(); }
}
View Code

  4.3 LinkedValueIterator

  LinkedHashMap的值迭代器,繼承自LinkedHashIterator,實現了Iterator接口,對LinkedHashMap中的值進行迭代。

final class LinkedValueIterator extends LinkedHashIterator
    implements Iterator<V> {
    public final V next() { return nextNode().value; }
}
View Code

  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(); }
}
View Code

5、總結

  HashMap迭代器與LinkedHashMap迭代器有不少類似的地方,對比進行學習效果更佳。迭代器要屏蔽掉底層的細節,提供統一的接口供用戶訪問。HashMap與LinkedHashMap的迭代器源碼分析就到此爲止,仍是很簡單的,謝謝各位園友觀看~

相關文章
相關標籤/搜索