Hashmap

Hashmap

程序概念
HashMap有兩個參數影響其性能:初始容量和加載因子。[1]基于哈希表的Map接口的實現。此實現提供所有可選的映射操作,并允許使用null值和null鍵。(除了非同步和允許使用null之外,HashMap類與Hashtable大緻相同。)此類不保證映射的順序,特别是它不保證該順序恒久不變。此實現假定哈希函數将元素适當地分布在各桶之間,可為基本操作(get和put)提供穩定的性能。叠代collection視圖所需的時間與HashMap實例的“容量”(桶的數量)及其大小(鍵-值映射關系數)成比例。所以,如果叠代性能很重要,則不要将初始容量設置得太高(或将加載因子設置得太低)。
    中文名: 外文名:Hashmap 别名: 基于:哈希表的Map接口的實現 參數:初始容量和加載因子 同步機制:不同步

設計思路

此實現假定哈希函數将元素正确分布在各桶之間,可為基本操作(get和put)提供穩定的性能。叠代集合視圖所需的時間與HashMap實例的“容量”(桶的數量)及其大小(鍵-值映射關系數)的和成比例。所以,如果叠代性能很重要,則不要将初始容量設置得太高(或将加載因子設置得太低)。HashMap的實例有兩個參數影響其性能:初始容量和加載因子。容量是哈希表中桶的數量,初始容量隻是哈希表在創建時的容量。加載因子是哈希表在其容量自動增加之前可以達到多滿的一種尺度。當哈希表中的條目數超出了加載因子與當前容量的乘積時,通過調用rehash方法将容量翻倍。

通常,默認加載因子(.75)在時間和空間成本上尋求一種折衷。加載因子過高雖然減少了空間開銷,但同時也增加了查詢成本(在大多數HashMap類的操作中,包括get和put操作,都反映了這一點)。在設置初始容量時應該考慮到映射中所需的條目數及其加載因子,以便最大限度地降低rehash操作次數。如果初始容量大于最大條目數除以加載因子,則不會發生rehash操作。

如果很多映射關系要存儲在HashMap實例中,則相對于按需執行自動的rehash操作以增大表的容量來說,使用足夠大的初始容量創建它将使得映射關系能更有效地存儲。注意,此實現不是同步的。如果多個線程同時訪問此映射,而其中至少一個線程從結構上修改了該映射,則它必須保持外部同步。(結構上的修改是指添加或删除一個或多個映射關系的操作;僅改變與實例已經包含的鍵關聯的值不是結構上的修改。)這一般通過對自然封裝該映射的對象進行同步操作來完成。如果不存在這樣的對象,則應該使用Collections.synchronizedMap方法來“包裝”該映射。最好在創建時完成這一操作,以防止對映射進行意外的不同步訪問。

因此,面對并發的修改,叠代器很快就會完全失敗,而不冒在将來不确定的時間任意發生不确定行為的風險。注意,叠代器的快速失敗行為不能得到保證,一般來說,存在不同步的并發修改時,不可能作出任何堅決的保證。快速失敗叠代器盡最大努力抛出。編寫依賴于此異常程序的方式是錯誤的,正确做法是:叠代器的快速失敗行為應該僅用于檢測程序錯誤。

重寫原則

不必對每個不同的對象都産生一個唯一的hashcode,隻要你的HashCode方法使get()能夠得到put()放進去的内容就可以了。即"不唯一原則"。生成hashcode的算法盡量使hashcode的值分散一些,不要很多hashcode都集中在一個範圍内,這樣有利于提高HashMap的性能。即"分散原則"。

至于第二條原則的具體原因,有興趣者可以參考BruceEckel的《ThinkinginJava》,在那裡有對HashMap内部實現原理的介紹。

分析

在Java的世界裡,無論類還是各種數據,其結構的處理是整個程序的邏輯以及性能的關鍵。

其實一個HashMap的實際容量就因子*容量,其默認值是16×0.75=12;這個很重要,對效率很一定影響!當存入HashMap的對象超過這個容量時,HashMap就會重新構造存取表。

兩個關鍵的方法,put和get:先有這樣一個概念,HashMap是聲明了Map,Cloneable,Serializable接口,和繼承了AbstractMap類,裡面的Iterator其實主要都是其内部類HashIterator和其他幾個iterator類實現,當然還有一個很重要的繼承了Map.Entry的Entry内部類。

這個就是判斷鍵值是否為空,并不很深奧,其實如果為空,它會返回一個staticObject作為鍵值,這就是為什麼HashMap允許空鍵值的原因。因為hash的算法有可能令不同的鍵值有相同的hash碼并有相同的table索引,如:key=“33”和key=Objectg的hash都是-8901334,那它經過indexfor之後的索引一定都為i,這樣在new的時候這個Entry的next就會指向這個原本的table[i],再有下一個也如此,形成一個鍊表,和put的循環對定e.next獲得舊的值。

上一篇:api接口

下一篇:可視化

相關詞條

相關搜索

其它詞條