以前一直覺得hash函數很深奧,上王珊的《數據庫實現原理》的時候,似乎明白了一點點,但是到學java
的時候,頻繁接觸到hashcode(),hashMap這些,就總在想這三者之間有關系嗎?hash函數是什么?hashcode(),
hashMap和hash函數又有什么關系呢?
今天終于對這個問題有了初步的學習和理解:
1.什么是hash函數:
1)來自:http://beyond911.bokee.com/1047973.html
什么是HASH函數(經典例子)??????????????????????????????????
讓我們先來了解一些基本知識,作作預熱只有這樣才能更好的了解hash。
Hash,一般翻譯做"散列",也有直接音譯為"哈希"的,就是把任意長度的輸入(又叫做預映射, pre-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間通常遠小于輸入的空間,不同的輸入可能會散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。
簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數。
HASH主要用于信息安全領域中加密算法,他把一些不同長度的信息轉化成雜亂的128位的編碼里,叫做HASH值. 也可以說,hash就是找到一種數據內容和數據存放地址之間的映射關系
2)來自:http://www.hour41.com/blog/hour41/entry/200701255
計算理論中,沒有Hash函數的說法,只有單向函數的說法。所謂的單向函數,是一個復雜的定義,大家可以去看計算理論或者密碼學方面的數據。用“人類”的語言描述單向函數就是:如果某個函數在給定輸入的時候,很容易計算出其結果來;而當給定結果的時候,很難計算出輸入來,這就是單項函數。各種加密函數都可以被認為是單向函數的逼近。Hash函數(或者成為散列函數)也可以看成是單向函數的一個逼近。即它接近于滿足單向函數的定義。
Hash函數還有另外的含義。實際中的Hash函數是指把一個大范圍映射到一個小范圍。把大范圍映射到一個小范圍的目的往往是為了節省空間,使得數據容易保存。除此以外,Hash函數往往應用于查找上。所以,在考慮使用Hash函數之前,需要明白它的幾個限制:
1. Hash的主要原理就是把大范圍映射到小范圍;所以,你輸入的實際值的個數必須和小范圍相當或者比它更小。不然沖突就會很多。
2. 由于Hash逼近單向函數;所以,你可以用它來對數據進行加密。
3. 不同的應用對Hash函數有著不同的要求;比如,用于加密的Hash函數主要考慮它和單項函數的差距,而用于查找的Hash函數主要考慮它映射到小范圍的沖突率。
3)自己的總結:
?? a)hash函數就是把任意長度的輸入(又叫做預映射, pre-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間通常遠小于輸入的空間,不同的輸入可能會散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。
例如,散列算法為求余的hash函數。
?? b)實際中的Hash函數是指把一個大范圍映射到一個小范圍。把大范圍映射到一個小范圍的目的往往是為了節省空間,使得數據容易保存。
?? c)在數據結構中,hash就是找到一種數據內容和數據存放地址之間的映射關系,比如,31對10求余后得1,就把31存放到第一個桶里(或者是第一塊內存單元中),即把數據和存放地址建立映射關系;
?? d)所以,有了數據內容和數據存放地址之間的映射關系,Hash函數往往應用于查找上。不過,利用hash函數的查找跟以前自己理解的不同,以前自己以為是通過hash函數就能立即找到存儲地址,就像HashMap中根據key立即能找到value一樣,其實不是這樣的,hash函數只不過是根據散列算法和解決沖突的方法來提供一種定位和查找的方式,hashmap中根據可以馬上找到value值是理所當然的,但是根據hash函數找到key值就不是立即的了。當然,為了方便查找,盡量使得hash函數無沖突,可以唯一確定地址是最理想的。娃哈哈,終于弄清楚這一點了!
?? e)Hash函數是指把一個大范圍映射到一個小范圍,所以hash函數是求余之類的壓縮函數,(比如,11,13的范圍壓縮為1,3),而不是10x+7這樣的擴散函數,(比如,11,13的范圍擴散為117,137);
?? f)由于Hash逼近單向函數;所以,你可以用它來對數據進行加密。
?? g)不同的應用對Hash函數有著不同的要求;比如,用于加密的Hash函數主要考慮它和單項函數的差距,而用于查找的Hash函數主要考慮它映射到小范圍的沖突率。
2.散列表相關知識的系統學習:
數據結構自考網:http://student.zjzk.cn/course_ware/data_structure/web/chazhao/chazhao9.4.1.htm
3.? JDK中HashMap的分析
1)來自:http://chinakite.javaeye.com/blog/25073
2)請問hashtable類里面的hash函數是怎么樣的?
來自:http://topic.csdn.net/t/20020311/09/567386.html
他是調用每個類自己本身的hashCode的方法來確定的?
? public?? synchronized?? Object?? put(Object?? key,?? Object?? value)?? {?
? ...?
? int?? hash?? =?? key.hashCode();//就是這里了?
? int?? index?? =?? (hash?? &?? 0x7FFFFFFF)?? %?? tab.length;?
? ...?
????????? }?
? 詳細請看java的源文件
String的散列值是由內容轉換來的,Object類的卻省散列函數返回對象地址轉換來的散列值。
4.面試題:
來自:http://www.javaref.cn/topics/Question/10566.html
問題:
a)請問哈希表 (hashtable) 是如何存儲數據的 ?
答案: Hashtable 是用來存儲 key 和 value 對的數據結構 , 根據設定的 hash 函數 H(key) 和處理沖突的方法將一組關鍵字( key )映象到一個有限的連續的地址集(區間)上,并以關鍵字在地址集中的“象”作為記錄在表中存儲位置,這種表便成為 hashtable.
b)是否兩個鍵值通過 hash 函數產生的映射地址會一樣?怎么辦?
答案 : 是,一般情況下,完全避免沖突是很難的。因為通常關鍵字集合會比目標地址空間大。哈希函數要盡量避免沖突(避免不同的關鍵字產生相同的 hash 值),使一組關鍵字的哈西地址盡可能的均勻分布在整個地址區間。所以有一些沖突處理方法:開放定址法,再哈希法,鏈地址法(用鏈表保存沖突的值),公共溢出區。?
關于哈希表,有個與實際編程更密切的問題可以一問:為保證邏輯上的正確性,哈希表對可以作為鍵值的類型有什么要求?? C++:除容器對元素類型的標準需求外,還需overload == 和 < Java:需override equals(邏輯上的正確性)和hashCode(性能) C#:需override Equals(邏輯上的正確性)和HashCode(性能)????