之前看一篇文章,讲哈希实际上是把一个大范围值域投影到一个小范围值域上的操作。比如:我们可以把一个字符串“老王很帅”转换成一个32位整数:Hash(string) ->int32;也可以把一个64位整数转化为32位整数:Hash(int64) -> int32;更可以把一个二进制文件转换为一个32位整数:Hash(bits) ->int32 等等。
那为什么要这样做呢?why?
老王不能完全回答这个问题,但是老王理解其中一个原因,就是将数据的多态归一化到了一个数据类型上。造成的结果就是,值域缩小,方便计算和检索。
最常见的数据结构,莫过于HashMap。我们可以将任何对象、数据存放到一个HashMap里,做到近似O(1)的插入和查找,简化了我们的实现、加速了我们的查找。
那哈希是怎么样实现的呢?how?
其实这里实际是两个问题:
1、一个key的hash值是如何计算的;
2、HashMap是如何实现存放和查找的。
那我们就来细细讲解一下上面这两个问题吧:
1、hash值的计算。
hash值的计算实际近似一个单向函数,他不要求你进行双向操作。所以,只要是你能想到的算法,基本都可以。但是,要尽量保证以下的原则:
a、可重入:同一个key,他的hash值要一样。比如:
int hash(Type key)
{
returnrand();
}
这个函数就不太符合要求,就是即使是同一个key,他得到的值也是基本不一样的。
b、尽量的分散:在key的数量够多的时候,他们求出来的hash值尽可能分散。比如:
int hash(Type key)
{
return1;
}
这个函数的效果就很差,不管key是什么,返回的值都一样。这样就导致hash以后,都集中到了一起。
只要满足以上的要求,我们就可以采用很多很多的算法,比如:md5、sha等摘要算法,也可以采用加法、乘法、位运算等等。以下是java的String类对于hash的实现:
publicint hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for