哈希表的原理,真的很難弄懂麼?

2020-12-16 劉小愛
【Java】基礎25:List、Set以及哈希表

昨天學習了幾種簡單數據結構,為何要了解數據結構?一方面的原因是因為集合的底層就是與其息息相關的。

ArrayList的底層數據結構:數組。LinkedList的底層數據結構:鍊表。TreeSet的底層數據結構:紅黑樹。HashSet的底層數據結構:哈希表。前天學習了Collection集合,其繼承體系圖如下:

今天就來了解Collection的子接口List,Set,以及它們各自的實現類。

一、List接口

List,翻譯就是列表的意思,列表有何特點?

它的元素是有序的。它是有索引的(Collection沒索引)。它的元素是可以重複的。Collection是List的父接口,那麼Collection中的所有方法,List都能直接拿來用。

List因為帶索引,所以它相對於Collection的特有方法基本都是索引相關的。

集合

中有四類方法是最常見的:

也就是增加元素,刪除元素,修改元素,查詢元素,簡稱就是增刪改查。

①增:add方法

可以直接添加元素,也可以根據索引添加元素。

②刪:remove方法

Collection中的remove方法是刪除對應的元素,List中可以根據索引來刪除元素。

③改:set方法

修改對應索引位的元素。

④查:get方法

得到對應索引位的元素。

1.ArrayList

這個集合很早前就學習過了,因為太常見了。

ArrayList是List的實現類,看名字就能看出來,其中Array就是數組的意思,顯而易見,ArrayList的底層就是數組。數組查詢快,故ArrayList常用來查詢數據。

那麼問題來了,數組長度不可變,ArrayList怎麼又可變了呢?

ArrayList默認是長度為10的數組,如果超過了,就會擴容。

如何擴容?

創建一個新的數組,再將舊數組複製進去,這樣長度就增加了。

所以本質上ArrayList長度可變是因為底層換了數組。

2.LinkedList

和ArrayList一樣,LinkedLIst也是List的實現類,其底層是鍊表。鍊表增刪快,故LinkedList常用來增刪數據。

集合中重要的是增刪改查四種方法,linkedList有幾種特殊的方法:

①addFirst方法:將元素添加到開頭。

其中push方法和addFirst方法一樣。

②addLast方法:將元素添加到結尾。

③removeFirst方法:將開頭元素移除並返回。

其中pop方法和removeFirst方法一樣。

④removeLast方法:將結尾元素移除並返回。

⑤getFirst方法:查詢獲取開頭元素。

⑥getLast方法:查詢獲取結尾元素。

這幾個方法都非常簡單,理解其中文意思也就知道其作用了。

其中有兩個方法比較特殊,官方解釋如下:

pop方法:從此列表所表示的堆棧處彈出一個元素。push方法:將元素推入此列表所表示的堆棧。不要看它解釋的這麼複雜,其實就是堆棧結構,堆棧有什麼特點?

先進先出,所以無論是增加還是刪除,都是最上面的元素。

二、Set接口

Set和List一樣,都是Collection的子接口。

特點和List剛好相反:

它的元素是無序的。它是沒有索引的。它的元素是不能重複的。集合有沒有索引的依據是什麼?

如果元素可以重複,比如說一個集合存了兩個元素,都是「劉小愛」,系統要如何判斷它們?所以就需要索引,這樣就能區分開:1索引位的劉小愛和2索引位的劉小愛,就算元素一樣,索引也不一樣。

故:元素可以重複,就有索引;元素不可以重複,就不需要索引。

Set因為沒有索引,所以和父接口Collection的方法一樣,沒有特殊方法。

那如何保證元素不重複?這就得依賴於hashCode和equals方法。

1.Object類的hashCode(哈希值)

Object類有一個toString方法,代碼如下:

toHexString:是轉換成十六進位的意思。

也就是說,我們直接列印Object對象得到的一串地址值就是hashCode的十六進位。

但是一個對象它真正的地址值,Java是不會輕易告訴我們的,一是我們知道了也沒啥用;二是黑客會拿它做壞事。於是Java就想了個辦法,對真正的地址進行加密,也就是hashCode的由來。

所以什麼叫hashCode?

hashCode是對真正的地址進行一種加密手段而得到的一串數字(什麼手段也不用去了解,除非你要去做黑客)。

那麼現在問題來了,有沒有可能存在多個對象地址,對應同一個hashCode呢?

答案是有的,只不過這種情況非常少見。也就是說:

不同的對象的真正地址是不可能相同的不同對象的hashCode是有可能相同的。如何理解這句話呢?

就是我們理論上是可以創建無數多個對象的,可以不停地在電腦上new對象,但是hashCode值是有限的,它是一個int類型的數據,最多也只有42億(2的32次方)多種可能。

所以不同的對象是有可能出現同一hashCode的,這種情況就叫哈希碰撞,只不過遇到這種情況概率微乎其微。

Object有一個方法就是hashCode,按照繼承的原則,所有類都有這個方法。

2.String的hashCode

String的hashCode方法是重寫過了的,跟真正的地址其實是沒關係的。

為何要這麼做?為了保證Set的元素不可重複。

hashCode值若是不相等,那這兩個元素必定不重複。hashCode值若是相等,這兩個元素大概率是重複的,但也有例外。如下圖幾種情況:

三、哈希表

Set的元素不可重複,這個問題該如何解決?

若是我的話,我肯定會想:將新的元素和Set中的每一個元素比較一遍不就可以了?如果有相等的,就不添加;如果有不相等的,就添加。

這樣做有問題麼,理論上是沒問題的,但是效率太低太低了,每次添加一個元素就要將元素遍歷一遍。

那些程式設計師大神為了解決這個問題,就弄出了哈希表。

所以什麼叫哈希表?

哈希表可以用來高效率解決元素不可重複這個問題,其本質就是:數組+鍊表+紅黑樹。

①哈希值就有點類似於數組中的索引,因為哈希值不同其元素必定不同。

數組查詢快,如果現在添加進來了一個元素,我根本不用遍歷,我就看有沒有相同的哈希值(相當於索引),直接就可以定位:

如果沒有相同的哈希值,直接添加進集合。如果有相同的哈希值,我再比較內容是否一樣。數組有一個問題,就是長度是一定的,所以若是元素過多時,需要擴容。但是哈希表數據結構比較複雜,還要提前擴容:哈希表中數組默認長度16,如果數組中的元素超過了75%就開始擴容。

②雖然哈希值一樣,但我還會比較它們的內容是否一樣,用equals方法比較內容是否一樣。

如果內容也一樣,重複元素,不添加進集合。如果內容不一樣,不是重複元素,添加進集合。③如果鍊表元素數量超過8,就將鍊表重構成紅黑樹。

鍊表查詢是很慢的,所以為了查詢效率,鍊表元素數量過多,就會重構成紅黑樹,紅黑樹查詢效率比鍊表要快。

這裡面涉及就到了兩個方法:hashCode方法和equals方法,它們一起能很好地判斷元素是否重複。

所以如果新建了一個對象,需要重寫hashCode方法和equals方法,這個在開發工具中直接使用Alt+Insert自動重寫方法。

HashSet的底層原理就是哈希表

其中LinkedHashSet又是HashSet的一個子類,其特點主要是有序的Set集合,存儲和取出的順序一致。總結

相關焦點

  • MySQL 資料庫的哈希表-愛可生
    這裡我們來介紹 MySQL 哈希索引。MySQL 哈希索引又基於哈希表(散列表)來實現,所以了解什麼是哈希表對 MySQL 哈希索引的理解至關重要。接下來,我們來一步一部介紹哈希表。1.鍊表鍊表也是一種線性表的存儲結構,但是和數組不一樣,存儲線性表數據的單元並非順序的。每個元素(也叫節點)包含了自己的值以及指向下一個元素地址的指針。比如圖 3,一個單線鍊表,MySQL 的 B+ 樹索引葉子節點就是一個鍊表結構。
  • Redis系列——漸進式哈希
    dict使用哈希表實現,這也是Redis性能十分強悍的原因之一,增刪改查的時間複雜度為O(1).上圖是我根據Redis源碼中定義的數據結構及網上資料參考畫的參考圖。隨著Redis的操作越來越多,dict中保存的數據量也會動態變化,當數據量增加或者減少到一定的程度,為了讓負載因子維持在一個合理的範圍內,Redis就會對dict的大小進行相應的擴容或者收縮。
  • 區塊鏈中神奇的哈希
    就是區塊鏈的哈希算法。大家知道,哈希就是一串數字的縮寫,我們看3007區塊可以縮寫為765677這串數字,正向的計算也就是從3007區塊數據進行的哈希運算是沒有問題的,3007區塊是和765677相對應的。但如果,我們反向計算,也就是說我們可以算出還有什麼樣的哈希也是765677,這會不會帶來什麼問題?
  • 如何讓普通鍋秒變不粘鍋,只需要弄懂這個物理原理
    就因為加了「不粘鍋」的元素,看起來和普通鍋沒什麼差別的「不粘鍋」就能翻好幾倍身價,今天小編就來帶大家揭秘「不粘鍋」的秘密,只要弄懂這個物理原理,任何一口普通鍋都可以成為不粘鍋。這個物理原理叫作萊頓弗羅斯特效應,是一個名叫赫爾曼的植物學家發現的,之所以沒有叫赫爾曼效應,是因為赫爾曼雖然發現了這一原理,卻沒有深入研究過。
  • 常見 Hash 算法的原理
    散列表(Hash table,也叫哈希表),是依據關鍵碼值(Key value)而直接進行訪問的數據結構。也就是說,它通過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數叫做散列函數,存放記錄的數組叫做散列表。比方我們存儲70個元素,但我們可能為這70個元素申請了100個元素的空間。70/100=0.7,這個數字稱為負載因子。
  • 改裝尾翼弄懂哪些門道?才能真正起作用
    【ZOL汽車電子】改裝界最常被安裝的就是尾翼了,有的尾翼真的很炫酷,很能增加車輛的回頭率,但尾翼不止是起裝飾作用的,它主要是為車輛提供穩定作用,而尾翼改裝也需要一些專業的知識,要弄懂其中的門道
  • 一文讀懂哈希時間鎖的合約機制、改進方向與應用場景
    哈希時間鎖是去中心化和去信任化環境中進行條件支付的基礎,是理解數字貨幣和數字資產的可編程性的基礎。除了對密碼學的應用,哈希時間鎖的核心是序貫博弈。多個哈希時間鎖可以組成多跳支付,是比特幣閃電網絡支付通道的基礎,也在用央行數字貨幣進行跨境支付有廣泛應用,被很多中央銀行所關注。相向而行的哈希時間鎖可以組成原子交換,在區塊鏈應用於證券結算以及去中心化交易所中有應用。
  • 銀行的動態口令令牌是什麼原理?
    有網銀的少年們一般都收到過銀行給的這樣一個令牌,俗稱動態口令,在支付的時候輸入自己的密碼和動態口令上的動態密碼,就能完成驗證,銀行就相信你不是壞人了,今天我們來簡述一下這個動態口令令牌是個什麼原理。 PS:本篇閱讀可能需要讀者有一些密碼學基礎,預警一下。
  • 維修製冰機一定要弄懂的四個工作步驟 .
    維修製冰機,一定要弄懂製冰機工作原理四步。
  • 單相電能表的工作原理
    一、功率表我們日常見到或聽到的大多是三相電能表、單相電能表,那麼功率表是什麼呢?有什麼用途?工作原理是什麼呢?下面我給大家了解一下。在測量功率時,電動系測量機構的固定線圈與負載串聯,轉動線圈串聯附加電阻後與負載並聯構成了功率表。功率表的結構示意圖如圖所示。固定線圈(電流線圈)用一個圓加一條水平的粗實線表示,用一條豎直的細實線表示轉動線圈(電壓線圈)。
  • 什麼是時間戳,什麼是哈希算法,網友:連女朋友都懂
    什麼是時間戳,什麼是哈希算法,網友:連女朋友都懂從百度「萊茨狗」到「網易星球」再到騰訊的「大家一起來捉妖」,這些網際網路巨頭紛紛入局區塊鏈。區塊鏈的關注也日益增高,每個人都想參與進來,區塊鏈想不火都難,今天就給大家說說與區塊鏈相關的幾個專業術語:時間戳和哈希算法一時間戳(timestamp)先讓我們看看專業上是怎麼說的,區塊鏈上時間戳就是保證每個區塊按照一定的次序相連。使區塊鏈上每一筆數據都具時間標記。打個比方說,在某個平臺發布了一篇文章,誰是原創的,誰是轉載的,怎麼證明呢?
  • 深度專訪 | 哈希街區創始人吳波:IPFS分布式存儲未來市值超千億美元
    近日,哈希街區HASH BLCOK創始人吳波先生(Fred)接受了鳳凰網財經的記者專訪,就哈希街區發展現狀、IPFS分布式存儲布局、新基建建設、新冠疫情影響等問題進行了回答,以下是訪談實錄:6.為什麼選擇在2019年成立哈希街區?您成立哈希街區的定位和初心是什麼?
  • 高考和競賽中的化學反應原理問題怎麼解決?
    化學反應原理是化學反應所遵循的基本原則和規律,主要包含化學熱力學和化學動力學的內容,涉及到化學反應能否進行;若可進行,能進行到什麼程度;可以進行,進行的程度也很大,進行的快慢如何等內容。化學反應原理實際是定性和定量研究化學反應的基本規律,是一個反應從可能性到現實性轉化的研究歷程,在歷年高考和競賽試題中佔有比重比較大,也是很多同學感覺很難的地方。今天會給大家介紹下怎麼掌握這部分內容。
  • 乾貨:57張動圖, 讓你搞懂高中物理原理
    要想把物理學好,先要把簡單的概念弄懂、簡單的題目做會。一是因為簡單的東西容易,這會增強學生學習的信心;二是因為更關鍵的是簡單的東西往往包含最基本的知識很理念,簡單的概念和規律是構成複雜現象的基礎和核心。任何複雜的題目都離不開最簡單的原理。
  • 57張動圖,讓你秒懂高中物理原理!考試次次拿第一
    要想把物理學好,先要把簡單的概念弄懂、簡單的題目做會。一是因為簡單的東西容易,這會增強學生學習的信心;二是因為更關鍵的是簡單的東西往往包含最基本的知識很理念,簡單的概念和規律是構成複雜現象的基礎和核心。任何複雜的題目都離不開最簡單的原理。
  • 冰刀的原理,你真的懂麼?
    最後一種說法是利用了「摩擦生熱」的原理,因為冰刀與冰面接觸摩擦產生熱量,使得冰面融化。三種說法各有道理,不知道眾位看官老爺,你們贊成哪一種呢
  • ThreadLocal的使用和實現原理
    ThreadLocal的使用和實現原理ThreadLocal是什麼?其實這其中會有哈希衝突,具體見下文。remove方法解決哈希衝突ThreadLocal中的hash code非常簡單,就是調用AtomicInteger的getAndAdd方法
  • 高檔車的「減速玻璃」黑科技,到底是什麼原理?原來真的只有忽悠
    在駕駛一些高檔汽車的時候,會明顯的覺得對於速度的感覺好像被「減緩」了一樣,具體來說就是同樣的表顯車速已經達到了80甚至是100公裡每小時以上,但是在駕駛高檔汽車時就感覺車速並沒有開普通車時那麼快。於是就有人說這是因為這些高檔汽車上搭載了「減速玻璃」這樣的黑科技,那麼事實真的是這樣嗎?內行人對此進行了分析和說明,下面就來一起看看,高檔車上的「減速玻璃」這個忽悠了我們幾十年黑科技,到底是什麼原理。原來真的是忽悠。其實所謂的「減速玻璃」根本是不存在的,準確的說以現有的科學技術,是無法通過車輛的前擋風玻璃,去實現真正意義上的減低車輛行駛速度的效果的。