一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - java HashMap 的工作原理詳解

java HashMap 的工作原理詳解

2020-06-11 16:24唐小娟 JAVA教程

本文主要介紹java HashMap 的資料,這里整理了相關資料,并詳細說明了HashMap的用法,有需要的小伙伴可以參考下

HashMap的工作原理是近年來常見的Java面試題。幾乎每個Java程序員都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之間的區別,那么為何這道面試題如此特殊呢?是因為這道題考察的深度很深。這題經常出現在高級或中高級面試中。投資銀行更喜歡問這個問題,甚至會要求你實現HashMap來考察你的編程能力。ConcurrentHashMap和其它同步集合的引入讓這道題變得更加復雜。讓我們開始探索的旅程吧!

先來些簡單的問題

“你用過HashMap嗎?” “什么是HashMap?你為什么用到它?”

幾乎每個人都會回答“是的”,然后回答HashMap的一些特性,譬如HashMap可以接受null鍵值和值,而Hashtable則不能;HashMap是非synchronized;HashMap很快;以及HashMap儲存的是鍵值對等等。這顯示出你已經用過HashMap,而且對它相當的熟悉。但是面試官來個急轉直下,從此刻開始問出一些刁鉆的問題,關于HashMap的更多基礎的細節。面試官可能會問出下面的問題:

“你知道HashMap的工作原理嗎?” “你知道HashMap的get()方法的工作原理嗎?”

你也許會回答“我沒有詳查標準的Java API,你可以看看Java源代碼或者Open JDK。”“我可以用Google找到答案。”

但一些面試者可能可以給出答案,“HashMap是基于hashing的原理,我們使用put(key, value)存儲對象到HashMap中,使用get(key)從HashMap中獲取對象。當我們給put()方法傳遞鍵和值時,我們先對鍵調用hashCode()方法,返回的hashCode用于找到bucket位置來儲存Entry對象。”這里關鍵點在于指出,HashMap是在bucket中儲存鍵對象和值對象,作為Map.Entry。這一點有助于理解獲取對象的邏輯。如果你沒有意識到這一點,或者錯誤的認為僅僅只在bucket中存儲值的話,你將不會回答如何從HashMap中獲取對象的邏輯。這個答案相當的正確,也顯示出面試者確實知道hashing以及HashMap的工作原理。但是這僅僅是故事的開始,當面試官加入一些Java程序員每天要碰到的實際場景的時候,錯誤的答案頻現。下個問題可能是關于HashMap中的碰撞探測(collision detection)以及碰撞的解決方法:

“當兩個對象的hashcode相同會發生什么?” 從這里開始,真正的困惑開始了,一些面試者會回答因為hashcode相同,所以兩個對象是相等的,HashMap將會拋出異常,或者不會存儲它們。然后面試官可能會提醒他們有equals()和hashCode()兩個方法,并告訴他們兩個對象就算hashcode相同,但是它們可能并不相等。一些面試者可能就此放棄,而另外一些還能繼續挺進,他們回答“因為hashcode相同,所以它們的bucket位置相同,‘碰撞'會發生。因為HashMap使用鏈表存儲對象,這個Entry(包含有鍵值對的Map.Entry對象)會存儲在鏈表中。”這個答案非常的合理,雖然有很多種處理碰撞的方法,這種方法是最簡單的,也正是HashMap的處理方法。但故事還沒有完結,面試官會繼續問:

“如果兩個鍵的hashcode相同,你如何獲取值對象?” 面試者會回答:當我們調用get()方法,HashMap會使用鍵對象的hashcode找到bucket位置,然后獲取值對象。面試官提醒他如果有兩個值對象儲存在同一個bucket,他給出答案:將會遍歷鏈表直到找到值對象。面試官會問因為你并沒有值對象去比較,你是如何確定確定找到值對象的?除非面試者直到HashMap在鏈表中存儲的是鍵值對,否則他們不可能回答出這一題。

其中一些記得這個重要知識點的面試者會說,找到bucket位置之后,會調用keys.equals()方法去找到鏈表中正確的節點,最終找到要找的值對象。完美的答案!

許多情況下,面試者會在這個環節中出錯,因為他們混淆了hashCode()和equals()方法。因為在此之前hashCode()屢屢出現,而equals()方法僅僅在獲取值對象的時候才出現。一些優秀的開發者會指出使用不可變的、聲明作final的對象,并且采用合適的equals()和hashCode()方法的話,將會減少碰撞的發生,提高效率。不可變性使得能夠緩存不同鍵的hashcode,這將提高整個獲取對象的速度,使用String,Interger這樣的wrapper類作為鍵是非常好的選擇。

如果你認為到這里已經完結了,那么聽到下面這個問題的時候,你會大吃一驚。“如果HashMap的大小超過了負載因子(load factor)定義的容量,怎么辦?”除非你真正知道HashMap的工作原理,否則你將回答不出這道題。默認的負載因子大小為0.75,也就是說,當一個map填滿了75%的bucket時候,和其它集合類(如ArrayList等)一樣,將會創建原來HashMap大小的兩倍的bucket數組,來重新調整map的大小,并將原來的對象放入新的bucket數組中。這個過程叫作rehashing,因為它調用hash方法找到新的bucket位置。

如果你能夠回答這道問題,下面的問題來了:“你了解重新調整HashMap大小存在什么問題嗎?”你可能回答不上來,這時面試官會提醒你當多線程的情況下,可能產生條件競爭(race condition)。

當重新調整HashMap大小的時候,確實存在條件競爭,因為如果兩個線程都發現HashMap需要重新調整大小了,它們會同時試著調整大小。在調整大小的過程中,存儲在鏈表中的元素的次序會反過來,因為移動到新的bucket位置的時候,HashMap并不會將元素放在鏈表的尾部,而是放在頭部,這是為了避免尾部遍歷(tail traversing)。如果條件競爭發生了,那么就死循環了。這個時候,你可以質問面試官,為什么這么奇怪,要在多線程的環境下使用HashMap呢?:)

熱心的讀者貢獻了更多的關于HashMap的問題:

1.為什么String, Interger這樣的wrapper類適合作為鍵? String, Interger這樣的wrapper類作為HashMap的鍵是再適合不過了,而且String最為常用。因為String是不可變的,也是final的,而且已經重寫了equals()和hashCode()方法了。其他的wrapper類也有這個特點。不可變性是必要的,因為為了要計算hashCode(),就要防止鍵值改變,如果鍵值在放入時和獲取時返回不同的hashcode的話,那么就不能從HashMap中找到你想要的對象。不可變性還有其他的優點如線程安全。如果你可以僅僅通過將某個field聲明成final就能保證hashCode是不變的,那么請這么做吧。因為獲取對象的時候要用到equals()和hashCode()方法,那么鍵對象正確的重寫這兩個方法是非常重要的。如果兩個不相等的對象返回不同的hashcode的話,那么碰撞的幾率就會小些,這樣就能提高HashMap的性能。

2.我們可以使用自定義的對象作為鍵嗎? 這是前一個問題的延伸。當然你可能使用任何對象作為鍵,只要它遵守了equals()和hashCode()方法的定義規則,并且當對象插入到Map中之后將不會再改變了。如果這個自定義對象時不可變的,那么它已經滿足了作為鍵的條件,因為當它創建之后就已經不能改變了。

3.我們可以使用CocurrentHashMap來代替Hashtable嗎?這是另外一個很熱門的面試題,因為ConcurrentHashMap越來越多人用了。我們知道Hashtable是synchronized的,但是ConcurrentHashMap同步性能更好,因為它僅僅根據同步級別對map的一部分進行上鎖。ConcurrentHashMap當然可以代替HashTable,但是HashTable提供更強的線程安全性。看看這篇博客查看Hashtable和ConcurrentHashMap的區別。

我個人很喜歡這個問題,因為這個問題的深度和廣度,也不直接的涉及到不同的概念。讓我們再來看看這些問題設計哪些知識點:

  1. hashing的概念
  2. HashMap中解決碰撞的方法
  3. equals()和hashCode()的應用,以及它們在HashMap中的重要性
  4. 不可變對象的好處
  5. HashMap多線程的條件競爭
  6. 重新調整HashMap的大小

總結

HashMap的工作原理
HashMap基于hashing原理,我們通過put()和get()方法儲存和獲取對象。當我們將鍵值對傳遞給put()方法時,它調用鍵對象的hashCode()方法來計算hashcode,讓后找到bucket位置來儲存值對象。當獲取對象時,通過鍵對象的equals()方法找到正確的鍵值對,然后返回值對象。HashMap使用鏈表來解決碰撞問題,當發生碰撞了,對象將會儲存在鏈表的下一個節點中。 HashMap在每個鏈表節點中儲存鍵值對對象。

當兩個不同的鍵對象的hashcode相同時會發生什么? 它們會儲存在同一個bucket位置的鏈表中。鍵對象的equals()方法用來找到鍵值對。

因為HashMap的好處非常多,我曾經在電子商務的應用中使用HashMap作為緩存。因為金融領域非常多的運用Java,也出于性能的考慮,我們會經常用到HashMap和ConcurrentHashMap。你可以查看更多的關于HashMap的文章:

HashMap和Hashtable的區別
HashMap和HashSet的區別

原文鏈接: Javarevisited 翻譯: ImportNew.com - 唐小娟
譯文鏈接: http://www.importnew.com/7099.html

延伸 · 閱讀

精彩推薦
  • JAVA教程Java中String、StringBuffer、StringBuilder的區別詳解

    Java中String、StringBuffer、StringBuilder的區別詳解

    java中String、StringBuffer、StringBuilder是編程中經常使用的字符串類,他們之間有什么區別呢?下面小編給大家總結了Java中String、StringBuffer、StringBuilder的區別詳...

    旭東的博客4992020-05-15
  • JAVA教程詳解Java編程中super關鍵字的用法

    詳解Java編程中super關鍵字的用法

    這篇文章主要介紹了Java編程中this與super關鍵字的用法,包括從內存結構方面分析super的作用域,需要的朋友可以參考下 ...

    孤傲蒼狼4742020-01-10
  • JAVA教程Java中使用json與前臺Ajax數據交互的方法

    Java中使用json與前臺Ajax數據交互的方法

    這篇文章主要為大家詳細介紹了Java中使用json與前臺Ajax數據交互的方法,分享Ajax獲取顯示Json數據的一種方法,感興趣的小伙伴們可以參考一下 ...

    海潛1562020-05-14
  • JAVA教程java使用任務架構執行任務調度示例

    java使用任務架構執行任務調度示例

    在Java 5.0之前啟動一個任務是通過調用Thread類的start()方法來實現的,5.0里提供了一個新的任務執行架構使你可以輕松地調度和控制任務的執行,并且可以建...

    java教程網1822019-10-31
  • JAVA教程Java程序員常犯的五個錯誤

    Java程序員常犯的五個錯誤

    這篇文章總結以前經驗針對java編程的一些習慣,給出一些關于java編程的建議: 當你開始成為一個程序員的時候,在編程的時候很容易陷入下面所述的一些...

    mrr3002019-12-28
  • JAVA教程JAVA流控及超流控后的延遲處理實例

    JAVA流控及超流控后的延遲處理實例

    這篇文章主要介紹了JAVA流控及超流控后的延遲處理,以實例形式較為詳細的分析了Java進行流量控制的技巧,具有一定參考借鑒價值,需要的朋友可以參考下 ...

    shichen20141662019-12-07
  • JAVA教程Java實現實時監控目錄下文件變化的方法

    Java實現實時監控目錄下文件變化的方法

    今天小編就為大家分享一篇關于Java實現實時監控目錄下文件變化的方法,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起...

    夢幻逝水2182019-06-21
  • JAVA教程JDBC數據源連接池配置及應用

    JDBC數據源連接池配置及應用

    這篇文章主要介紹JDBC建立數據庫連接的兩種方式,使用配置數據源的方式連接數據庫,效率更高,推薦使用,希望能給大家做一個參考。 ...

    kingxss1282020-05-15
主站蜘蛛池模板: 色老板美国在线观看 | tk白嫩玉足脚心vk | 久久99精品久久久久久园产越南 | 国产肥女bbwbbw | 丰腴尤物贵妇浪荡小说 | 国产精品综合在线 | ak福利影院 | 欧美精品色精品一区二区三区 | 成人资源影音先锋久久资源网 | 九九久久国产 | 国产成人免费片在线观看 | 嗯啊好爽视频 | 四虎精品成人a在线观看 | 九九热视频 这里有精品 | 哇嘎在线精品视频在线观看 | 日韩免费高清专区 | 草草视频在线观看 | 成年人视频免费在线播放 | jizz女16处| bbox撕裂bass孕妇| 操儿媳小说 | 欧美特黄特色aaa大片免费看 | 日本搜子同屋的日子2国语 日本爽p大片免费观看 | 555www成人网| 黄a 大片a v 永久免费 | 欧美日韩三区 | 美女翘臀跪床被打屁股作文 | 免费一级毛片在线播放 | 色狠狠婷婷97 | 国产精品色片 | 99爱在线观看精品视频 | bl文全肉高h湿被灌尿 | 波多野结衣178部中文字幕 | 国语刺激对白勾搭视频在线观看 | 久见久热 这里只有精品 | yellow最新视频2019 | 白丝爆动漫羞羞动漫软件 | 日本在线视频网址 | 欧美a欧美1级 | 国产一二区视频 | 亚洲成人黄色网址 |