Java Hashtable 源碼分析

Hashtable 提供的功能

  • Hashtable是一個線程安全的Map,其線程安全是通過在各個方法上加上synchronized關(guān)鍵字實現(xiàn)的喇勋,即:該類只能被一個線程所使用,其他調(diào)用該類時會阻塞等待;
  • 實現(xiàn)了哈希表偎行,映射key到value川背;
  • key和value都不能為null(因為需要調(diào)用hashCode()方法,如果為null的話就會拋出NPE)蛤袒,key類型必須實現(xiàn)hashCode()和equals()方法熄云;
  • put(K k,V v);
  • get(K k,V v);
  • Hashtable沒有實現(xiàn)hash沖突的解決方案,沖突需要按自己的邏輯實現(xiàn)妙真,它只提供了哈希表自動擴容的功能缴允;
  • 出現(xiàn)hash沖突時,采用單向鏈表來儲存沖突的元素珍德。

Hashtable 涉及到的概念

  • 初始化容量:key數(shù)組初始長度练般,默認值是11
  • 負載系數(shù)(load factor):即到達容量的百分比時,哈希表就會重新hash到一個新容量的哈希表中,取值范圍是:<1.0 的百分數(shù) 默認取值是.75(75%锈候,當加入的鍵值對數(shù)量達到初始容量的75%時薄料,繼續(xù)加入的話會重新hash到一個新的容量的哈希表中)
  • 閾(yù)值:threshold=初始化容量*0.75和Integer.MAX_VALUE-8(注:Integer.MAX_VALUE=0x7FFFFFFF)
    中較小值
  • 重新Hash:加入元素時,當數(shù)組大小大于等于閾值時泵琳,key數(shù)組的容量會左移2位后+1即:原容量*4+1摄职,然后按新的容量hash后放入新的數(shù)組中誊役。
  • 哈希函數(shù):(key.hashCode() & 0x7FFFFFFF) % key數(shù)組現(xiàn)在的長度

Hashtable常用方法分析

  • put(K k,V v);
    添加元素到哈希表時,判斷元素是否存在谷市,如果存在(key的hash相同并且值也相同)的話蛔垢,就會覆蓋掉原來的元素,并返回原來的值歌懒;如果不存在的話啦桌,就會直接新建一個元素,若產(chǎn)生hash沖突則將舊元素鏈接到新元素的尾部及皂。
  • get(K k);
    獲取元素時甫男,先根據(jù)key的hash獲取到對應(yīng)key數(shù)組的下標,獲取對應(yīng)的元素(因為數(shù)組元素的值是一個單鏈表验烧,所以如果當前的值不匹配時就需要判斷鏈表的下一個元素)板驳。

處理 Hash沖突

Hashtable 處理 Hash沖突 時通過單鏈表。碍拆。

涉及的基本概念

  • 位運算
  • 數(shù)組
  • 哈希表
  • 單鏈表
  • Java transient 關(guān)鍵字原理
  • Java 序列化若治、反序列化以及自定義序列化、反序列話邏輯(writeObject(ObjectOutputStream o)和readObject(ObjectInputStream i))

存在未理解之處

Hashtable的count字段是什么時候初始化的感混?從賦值來看是通過readObject()方法來實現(xiàn)的端幼。但是具體實現(xiàn)需要回去取研讀下《Java編程思想》序列化章節(jié)內(nèi)容。

private transient int count;

未理解之處的解答

  • Hashtable的count字段是什么時候初始化的弧满?因為該變量是類變量編譯的時候會自動賦值婆跑。可以總結(jié)下Java各種類型的變量庭呜。

模擬hash沖突

可以根據(jù)hash函數(shù)(key.hashCode() & 0x7FFFFFFF) % key數(shù)組現(xiàn)在的長度來模擬hash沖突滑进,只要key的hashCode是相同但是又不equals()的就是Hash沖突。如下實例:

public class MyKey implements Serializable {
    private int i;

    public MyKey(int i) {
        this.i = i;
    }

    @Override
    public int hashCode() {
        if (i % 2 == 0) {
            return 1;
        } else {
            return 2;
        }
    }

}

Hashtable處理hash沖突

如下實例:

public static void main(String[] args) {
    Hashtable<MyKey, Integer> map = new Hashtable<>();
    for (int i = 0; i < 11; i++) {
        map.put(new MyKey(i), i);
    }
    map.get(new MyKey(1));
}

如何在IDEA調(diào)試模式下查看儲存結(jié)構(gòu)募谎?

Hashtable在IDEA下的默認視圖:


Java-Hashtable-data-structure-default-view.png

如何查看對象視圖扶关?如下圖操作:

Java-Hashtable-data-structure-object-view.png

對象視圖如下

Java-Hashtable-data-structure.png

從如上對象視圖可以看出Hashtable的table字段的具體存儲方式:
table數(shù)組中有兩個元素,一個是MyKey.i=10数冬,一個是Mykey.i=9,按如上查看對象視圖的方法查看這兩個元素的對象視圖查看java.util.Hashtable.Entry#next屬性节槐,可以看到MyKey.i=10的next屬性值是MyKey.i=8...
各元素的具體結(jié)構(gòu)如下:

MyKey.i=10.next -> MyKey.i=8
MyKey.i=8.next -> MyKey.i=0
MyKey.i=0.next -> MyKey.i=2
MyKey.i=2.next -> MyKey.i=4
MyKey.i=4.next -> MyKey.i=6
MyKey.i=6.next -> null


MyKey.i=9.next -> MyKey.i=1
MyKey.i=1.next -> MyKey.i=3
MyKey.i=3.next -> MyKey.i=5
MyKey.i=5.next -> MyKey.i=7
MyKey.i=7.next -> null

為什么順序不是按加入的順序的呢,而是一部分到過來的吉执?
因為Hashtable的key數(shù)組默認大小是11疯淫,當加入11個元素時,會自動擴容戳玫,在加入第8個元素時會rehash一次熙掺,rehash時是將新哈希表中的元素作為后面加入元素的next的,所有就會出現(xiàn)部分元素順序相反咕宿。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末币绩,一起剝皮案震驚了整個濱河市蜡秽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缆镣,老刑警劉巖芽突,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異董瞻,居然都是意外死亡寞蚌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門钠糊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挟秤,“玉大人,你說我怎么就攤上這事抄伍∷腋眨” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵截珍,是天一觀的道長攀甚。 經(jīng)常有香客問我,道長岗喉,這世上最難降的妖魔是什么秋度? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮钱床,結(jié)果婚禮上静陈,老公的妹妹穿的比我還像新娘。我一直安慰自己诞丽,他們只是感情好,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布拐格。 她就那樣靜靜地躺著僧免,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捏浊。 梳的紋絲不亂的頭發(fā)上懂衩,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天,我揣著相機與錄音金踪,去河邊找鬼浊洞。 笑死,一個胖子當著我的面吹牛胡岔,可吹牛的內(nèi)容都是我干的法希。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼靶瘸,長吁一口氣:“原來是場噩夢啊……” “哼苫亦!你這毒婦竟也來了毛肋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤屋剑,失蹤者是張志新(化名)和其女友劉穎润匙,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唉匾,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡孕讳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了巍膘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厂财。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖典徘,靈堂內(nèi)的尸體忽然破棺而出蟀苛,到底是詐尸還是另有隱情,我是刑警寧澤逮诲,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布帜平,位于F島的核電站,受9級特大地震影響梅鹦,放射性物質(zhì)發(fā)生泄漏裆甩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一齐唆、第九天 我趴在偏房一處隱蔽的房頂上張望嗤栓。 院中可真熱鬧,春花似錦箍邮、人聲如沸茉帅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堪澎。三九已至,卻和暖如春味滞,著一層夾襖步出監(jiān)牢的瞬間樱蛤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工剑鞍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昨凡,地道東北人。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓蚁署,卻偏偏與公主長得像便脊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子光戈,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,261評論 0 16
  • 移步數(shù)據(jù)結(jié)構(gòu)--容器匯總(java & Android)由于 HashMap 底層涉及到太多方面妒御,一篇文章總是不能...
    凱玲之戀閱讀 831評論 0 5
  • 一解愤、HashMap概述 HashMap基于哈希表的Map接口的實現(xiàn)。此實現(xiàn)提供所有可選的映射操作乎莉,并允許使用nul...
    小陳阿飛閱讀 637評論 0 2
  • 本系列出于AWeiLoveAndroid的分享送讲,在此感謝,再結(jié)合自身經(jīng)驗查漏補缺惋啃,完善答案哼鬓。以成系統(tǒng)。 Java基...
    濟公大將閱讀 1,528評論 1 6
  • 2019年一年的成長边灭,我已經(jīng)做到的异希,開了自己的線下讀書會,分享會绒瘦, 持續(xù)坤達里尼瑜伽早課自五月開始称簿,開始支持他人,...
    美麗selina閱讀 447評論 0 9