发现hash在面试和实际应用中是一个很热门的话题,大家都知道,在java中,hashmap和hashset都是通过hash进行存储的,查找的速度非常的快,可以用来处理海量数据。那么,我想提出以下几个问题:
1、hash到底是什么东东?
hash啊,我个人理解,就是通过一个hash函数(这个函数的写法是关键,写得好,冲突少),对某个对象进行求值,得到一个hash值,就像MD5一样,对一个字符串进行求MD5,不过MD5是唯一的,不会重复(理论上是这样),而hash值可能会重复,例如,对对象A求hash,得到的hash值是100,对对象B求hash,得到的hash值也是100,那么,我们就说产生了冲突,这不是一个好的现象,取决于hash函数的算法是否OK。
2、产生了冲突,那么怎么办捏?
冲突是不可避免的,既然不能避免,那么我们就来处理(待会我会讲讲如何最大限度的避免),书上网上方法我总结了一下,主要有如下几种:
1. 开放寻址法;
Hi=(H(key) + di) MOD m, i=1,2,…, k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列,可有下列三种取法:
A. di=1,2,3,…, m-1,称线性探测再散列;
B. di=1^2, (-1)^2, 2^2,(-2)^2, (3)^2, …, ±(k)^2,(k<=m/2)称二次探测再散列;
C. di=伪随机数序列,称伪随机探测再散列。 ==
2. 再散列法:Hi=RHi(key), i=1,2,…,k RHi均是不同的散列函数,即在同义词产生地址冲突时计算另一个散列函数地址,直到冲突不再发生,这种方法不易产生“聚集”,但增加了计算时间。
3. 链地址法(拉链法)
4. 建立一个公共溢出区
具体详细,大家百度下看看就知道了。
3、解释下啥是装填因子
java中,hash的默认装填因子是0.75,那么啥是装填因子捏?举个例子,你要对5个对象进行hash,而内存中,准备了20个位子,来放他们,那么,最后,就有15个空位啦,那么装填因子就是 5/20 ,装填因子就为0.45啦,你装填因子越小,说明你备用的内存空间越多,装填因子的选定,可以影响冲突的产生,百度百科上说,装填因子越小,冲突越小(这个不是很理解,为啥捏?)
4、啥是hash表?
理解成hash值和对象一对一映射的一个表,表的大小为对象的大小。
5、常用的构造hash函数的方法(摘至百科)
散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位ǐ
A. 直接寻址法:取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数)
B. 数字分析法
C. 平方取中法
D. 折叠法
E. 随机数法
F. 除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key MOD p, p<=m。不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选的不好,容易产生同义词。
6、啥是关键码
关键码就是在对某个对象求hash的时候,hash函数是根据那个字段来进行求hash的,例如: y=mx; y是hash函数,x就是那个关键码。
7、那如何生产出一个高效,冲突少,分布均匀的hash函数呢?(淘宝面试问了我这个问题,后来我问了我们老师,现在在等答案,有答案了再更新吧)
1、质数理论,就是除留余数法那个除数(除数也就是内存的长度)要是一个质数( 这个是TB给我的答案 )
2、装填因子选定要合适,理论上越小越好(这个答案我也不是很理解)
3、、、、、
4、、、、
想到的基本就这样写了,欢迎大家跟帖补充