程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java HashMap 的任務道理詳解

java HashMap 的任務道理詳解

編輯:關於JAVA

java HashMap 的任務道理詳解。本站提示廣大學習愛好者:(java HashMap 的任務道理詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是java 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的年夜小
  7. 總結

    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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved