2013-05-07 83 views
7

考慮這個類:完美的散列函數和福利

public final class MyDate { 
     private int year, month, day; 

     public MyDate(int year, int month, int day) { 
      this.year = year; 
      this.month = month; 
      this.day = day; 
     } 

     //Some stuff 

     @Override 
     public int hashCode() { 
      return ((year << 4) | month) << 5 | day; 
     } 
} 

這是一個完美的散列函數,因爲在存儲有:

enter image description here

因此,在紅,5 bits店一天( 1到31),黃色4 bits存儲月份(1到12),其他存儲年份(1到16777215)。

完美的hashFunction有什麼好處? AFAIK,它可以保證在HashSet中添加/刪除/包含在O(1)中,但是我可以獲得其他好處嗎?

我看到許多散列函數使用素數,構建一個散列函數的最佳方式是什麼(我認爲創建一個完美的散列函數是不常見/罕見的)?


編輯:

關於素數 - >回答here

+0

如果底層哈希數組的大小適合所有可能的值(這對於jdk HashSet/HashMap來說不太可能),那麼您的完美哈希函數纔有用。 – jtahlborn 2013-05-07 20:08:09

+0

我不明白爲什麼當我需要一個新的實例時,我可以輕鬆創建一個新的實例,爲什麼要在一個哈希集中添加一個日期? – Andy 2013-05-07 20:50:29

+0

@Andy這是一個例子 – user2336315 2013-05-07 20:52:43

回答

8

一個完美的哈希函數可以保證你不會有任何衝突。然而,爲了能夠使用它,你必須確切地知道需要被散列的關鍵值集合,而這往往不是這種情況。

其他並不完美但仍然不錯的散列函數(以及衝突解決機制)沒有這個要求,並且計算速度非常快,所以它們通常更合適。

1

根據Juampi它是快速的。 速度有多快?大約O(1)。Redis是通過哈希表在內存中進行恆定時間查詢的絕佳示例。

如果散列結果中沒有確切的一個元素桶,那麼您需要使用equals來比較每個項目,以便查找O(1加z),其中z是桶大小。

但是很慢的哈希函數肯定不是一個好主意。