jdk1.8 HashMap底層數據結構:散列表+鏈表+紅黑樹(圖解+源碼)

1、前言node

  本文由jdk1.8源碼整理而得,附自制jdk1.8底層數據結構圖,並截取部分源碼加以說明結構關係。算法

2、jdk1.8 HashMap底層數據結構圖數據結構

  

3、源碼spa

  1.散列表(Hash table,也叫哈希表):code

/** * 表,第一次使用時初始化(而非實例化集合時進行初始化),並根據須要調整大小。當分配時,長度老是2的冪。(在某些操做中,咱們還容許長度爲零,以容許當前不須要的引導機制。)
   */ transient Node<K,V>[] table;

  2.鏈表:blog

/** * Basic hash bin node, used for most entries. (See below for * TreeNode subclass, and in LinkedHashMap for its Entry subclass.) */
    static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next;
     …… }

  3.紅黑樹:源碼

/** * Entry for Tree bins. Extends LinkedHashMap.Entry (which in turn * extends Node) so can be used as extension of either regular or * linked node. */
    static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> { TreeNode<K,V> parent;  // red-black tree links
        TreeNode<K,V> left; TreeNode<K,V> right; TreeNode<K,V> prev;    // needed to unlink next upon deletion
        boolean red; …… }

4、問題探究hash

  1.散列表後面跟的「鏈表、紅黑樹」是怎麼來的,都解決了哪些問題?it

    答:io

    ①鏈表的由來:Hash碰撞:不一樣的元素經過hash算法可能會獲得相同的hash值,若是都放同一個桶裏,後面放進去的就會覆蓋前面放的,因此爲了解決hash碰撞時元素被覆蓋的問題,就有了在桶裏放鏈表。

    ②紅黑樹的由來:假設如今HashMap集合中大多數的元素都放到了同一個桶裏(由hash值計算而得的桶的位置相同),那麼這些元素就在這個桶後面連成了鏈表。如今須要查詢某個元素,那麼此時的查詢效率就很慢了,它是在作鏈表查詢( O(N) 的查詢效率)。爲了解決這個問題,就引入了紅黑樹( log(n) 的查詢效率):當鏈表到達必定長度時就在鏈表的後面建立紅黑樹。

    ③其實,「儘可能避免hash 衝突,讓元素較爲均勻的放置到每一個桶」纔是查詢效率最高的( O(1) 的查詢效率),這和hash算法的實現息息相關,這裏不作深究。

  2.如圖可知,散列表後面跟的數據結構有多是鏈表,也有多是紅黑樹。散列表後面跟什麼數據結構是怎麼肯定的?

    答:

    ①鏈表節點轉換成紅黑樹節點的閾值, 節點數 >= 8 就轉:

      static final int TREEIFY_THRESHOLD = 8;

    ②紅黑樹節點轉換鏈表節點的閾值, 節點數 <= 6 就轉:

      static final int UNTREEIFY_THRESHOLD = 6;

    ③轉紅黑樹時, table的最小長度:

      static final int MIN_TREEIFY_CAPACITY = 64;

相關文章
相關標籤/搜索