Map集合、散列表、紅黑樹介紹

前言

聲明,本文用得是jdk1.8html

前面已經講了Collection的總覽和剖析List集合:java

本來我是打算繼續將Collection下的Set集合的,結果看了源碼發現:Set集合實際上就是HashMap來構建的git

因此,就先介紹Map集合、散列表和紅黑樹吧github

看這篇文章以前最好是有點數據結構的基礎:c#

固然了,若是講得有錯的地方還請你們多多包涵並不吝在評論去指正~數組

1、Map介紹

1.1爲何須要Map

前面咱們學習的Collection叫作集合,它能夠快速查找現有的元素。微信

而Map在《Core Java》中稱之爲-->映射..數據結構

映射的模型圖是這樣的:函數

那爲何咱們須要這種數據存儲結構呢???舉個例子學習

  • 做爲學生來講,咱們是根據學號來區分不一樣的學生。只要咱們知道學號,就能夠獲取對應的學生信息。這就是Map映射的做用!

生活中還有不少這樣的例子:只要你掏出身份證(key),那就能夠證實是你本身(value)

1.2Map與Collection的區別

1.3Map的功能

下面咱們來看看Map的源碼:

簡單經常使用的Map功能有這麼一些:

下面用紅色框框圈住的就是Map值得關注的子類:

2、散列表介紹

不管是Set仍是Map,咱們會發現都會有對應的-->HashSet,HashMap

首先咱們也先得回顧一下數據和鏈表

  • 鏈表和數組均可以按照人們的意願來排列元素的次序,他們能夠說是有序的(存儲的順序和取出的順序是一致的)
  • 但同時,這會帶來缺點:想要獲取某個元素,就要訪問全部的元素,直到找到爲止。
  • 這會讓咱們消耗不少的時間在裏邊,遍歷訪問元素~

而還有另外的一些存儲結構:不在乎元素的順序,可以快速的查找元素的數據

  • 其中就有一種很是常見的:散列表

2.1散列表工做原理

散列表爲每一個對象計算出一個整數,稱爲散列碼根據這些計算出來的整數(散列碼)保存在對應的位置上

在Java中,散列表用的是鏈表數組實現的,每一個列表稱之爲桶。【以前也寫過桶排序就這麼簡單,能夠回顧回顧】

一個桶上可能會遇到被佔用的狀況(hashCode散列碼相同,就存儲在同一個位置上),這種狀況是沒法避免的,這種現象稱之爲:散列衝突

  • 此時須要用該對象與桶上的對象進行比較,看看該對象是否存在桶子上了~若是存在,就不添加了,若是不存在則添加到桶子上
  • 固然了,若是hashcode函數設計得足夠好,桶的數目也足夠,這種比較是不多的~
  • JDK1.8中,桶滿時會從鏈表變成平衡二叉樹

若是散列表太滿,是須要對散列表再散列,建立一個桶數更多的散列表,並將原有的元素插入到新表中,丟棄原來的表~

  • 裝填因子(load factor)決定了什麼時候對散列表再散列~
  • 裝填因子默認爲0.75,若是表中超過了75%的位置已經填入了元素,那麼這個表就會用雙倍的桶數自動進行再散列

固然了, 在後面閱讀源碼的時候會繼續說明的,如今簡單瞭解一下便可~

擴展閱讀:

3、紅黑樹介紹

上面散列表中已經提過了:若是桶數滿的時候,JDK8是將鏈表轉成紅黑樹的~。而且,咱們的TreeSet、TreeMap底層都是紅黑樹來實現的。

因此,在這裏學習一波紅黑樹究竟是啥玩意。

以前涉及過二叉樹的文章:

在未學習以前,咱們多是聽過紅黑樹這麼一個數據結構類型的,還有其餘什麼B/B+樹等等,反正是比較複雜的數據結構了~~~

各類常見的樹的用途:

來源:
https://www.zhihu.com/question/30527705/answer/52527887

3.1回顧二叉查找樹

首先咱們來回顧一下:利用二叉查找樹的特性,咱們通常來講能夠很快地查找出對應的元素。

但是二叉查找樹也有個例(最壞)的狀況(線性):

上面符合二叉樹的特性,可是它是線性的,徹底沒樹的用處~

樹是要「均衡」才能將它的優勢展現出來的~,好比下面這種:

所以,就有了平衡樹這麼一個概念~紅黑樹就是一種平衡樹,它能夠保證二叉樹基本符合矮矮胖胖(均衡)的結構

3.2知新2-3樹

講到了平衡樹就不得不說最基礎的2-3樹,2-3樹長的是這個樣子:

在二叉查找樹上,咱們插入節點的過程是這樣的:小於節點值往右繼續與左子節點比,大於則繼續與右子節點比,直到某節點左或右子節點爲空,把值插入進去。這樣沒法避免偏向問題

而2-3樹不同:它插入的時候能夠保持樹的平衡

在2-3樹插入的時能夠簡單總結爲兩個操做:

  • 合併2-節點爲3-節點,擴充將3-節點擴充爲一個4-節點
  • 分解4-節點爲3-節點,節點3-節點爲2-節點
  • ........至使得樹平衡~

合併分解的操做仍是比較複雜的,要分好幾種狀況,代碼量很大~這裏我就不介紹了,由於要學起來是一大堆的,很麻煩~

3.3從2-3樹到紅黑樹

因爲2-3樹爲了保持平衡性,在維護的時候是須要大量的節點交換的!這些變換在實際代碼中是很複雜的,大佬們在2-3樹的理論基礎上發明了紅黑樹(2-3-4樹也是一樣的道理,只是2-3樹是最簡單的一種狀況,因此我就不說2-3-4樹了)。

  • 紅黑樹是對2-3查找樹的改進,它能用一種統一的方式完成全部變換

紅黑樹是一種平衡二叉樹,所以它沒有3-節點。那紅黑樹是怎麼將3-節點來改進成全都是二叉樹呢?

紅黑樹就字面上的意思,有紅色的節點,有黑色的節點

咱們能夠將紅色節點的左連接畫平看看:

一顆典型的二叉樹:

將紅色節點的左連接畫平以後:獲得2-3平衡樹:

3.4紅黑樹基礎知識

前面已經說了,紅黑樹是在2-3的基礎上實現的一種樹,它可以用統一的方式完成全部變換。很好理解:紅黑樹也是平衡樹的一種,在插入元素的時候它也得保持樹的平衡,那紅黑樹是以什麼的方式來保持樹的平衡的呢?

紅黑樹用的是也是兩種方式來替代2-3樹不斷的節點交換操做:

  • 旋轉:順時針旋轉和逆時針旋轉
  • 反色:交換紅黑的顏色
  • 這個兩個實現比2-3樹交換的節點(合併,分解)要方便一些

紅黑樹爲了保持平衡,還有制定一些約束,遵照這些約束的才能叫作紅黑樹:

  1. 紅黑樹是二叉搜索樹。
  2. 根節點是黑色
  3. 每一個葉子節點都是黑色的空節點(NIL節點)
  4. 每一個紅色節點的兩個子節點都是黑色。(從每一個葉子到根的全部路徑上不能有兩個連續的紅色節點)
  5. 從任一節點到其每一個葉子的全部路徑都包含相同數目的黑色節點(每一條樹鏈上的黑色節點數量(稱之爲「黑高」)必須相等)

3.5紅黑樹總結

紅黑樹能夠說是十分複雜的,我在學習的時候並無去認真細看當中的處理細節,只是大概的過了一遍,知道了總體~

有了前輩不少優質的資料,相信要等到想要理解其中的細節,花點力氣和時間仍是能夠掌握一二的。

紅黑樹參考資料:

4、總結

這篇主要介紹了Map集合的基礎知識,瞭解Map的經常使用子類~

簡單介紹了散列表和紅黑樹,他倆做爲Hashxxx和Treexxx的底層,瞭解其總體思想和相關基礎在後續看源碼也不至於那麼懵~

後續會去看Map經常使用子類的源碼,文章敬請期待~~~~

若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:Java3y。爲了你們方便,剛新建了一下qq羣:742919422,你們也能夠去交流交流。謝謝支持了!但願能多介紹給其餘有須要的朋友

參考資料:

  • 《Core Java》
相關文章
相關標籤/搜索