2013-05-07 85 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是桶大小。

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