Hash算法原理

转自souso问问:http://wenwen.soso.com/z/q181569235.htm

我来做一个比喻吧。
   我们有很多的小猪,每个的体重都不一样,假设体重分布比较平均(我们考虑到公斤级别),我们按照体重来分,划分成100个小猪圈。
    然后把每个小猪,按照体重赶进各自的猪圈里,记录档案。

    好了,如果我们要找某个小猪怎么办呢?我们需要每个猪圈,每个小猪的比对吗? 当然不需要了。

   我们先看看要找的这个小猪的体重,然后就找到了对应的猪圈了。 在这个猪圈里的小猪的数量就相对很少了。 我们在这个猪圈里就可以相对快的找到我们要找到的那个小猪了。

   对应于hash算法。
   就是按照hashcode分配不同的猪圈,将hashcode相同的猪放到一个猪圈里。 查找的时候,先找到hashcode对应的猪圈,然后在逐个比较里面的小猪。所以问题的关键就是建造多少个猪圈比较合适。

   如果每个小猪的体重全部不同(考虑到毫克级别),每个都建一个猪圈,那么我们可以最快速度的找到这头猪。缺点就是,建造那么多猪圈的费用有点太高了。

    如果我们按照10公斤级别进行划分,那么建造的猪圈只有几个吧,那么每个圈里的小猪就很多了。我们虽然可以很快的找到猪圈,但从这个猪圈里逐个确定那头小猪也是很累的。

     所以,好的hashcode,可以根据实际情况,根据具体的需求,在时间成本(更多的猪圈,更快的速度)和空间本(更少的猪圈,更低的空间需求)之间平衡。

 

    hashcode,一个不太好理解,也常被我们忽视的一个概念。然而,hashcode还有对我们有用的东西。
    java给我们提供了两种判断对象对等的方式。如果我们判断两个对象是否相等,那么直接用“==”运算就可以了。然而,判断两个对象对等,就没有那么简单了。
在java中,我们常常通过equals()方法来判断两个对象的对等。其实,我么还可以通过hashCode()来判断两个对象的对等。

看下面的例子:

import java.util.List;

public class MyBag{
float money;
List books;
}
    我们如何判断两个MyBag对象是对等的呢?也就是说,如果有两个MyBag的对象bag1和bag2,通过什么的办法能说明这个两个对象是相同的呢?
    先声名两个概念:
    两个对象相等,指的是,两个引用指向了同一个对象,也就是说,指向了内存中的同一个地址。两个对象相同(对等),指得是两个对象的任何属性都相等,但是,不是一个对象。

    所以,对于上面的MyBag的对象对等,那么,两个对象的money要一样,同时,books要对等。那么如何去判断呢?我们通常会自己去实现equals()方法去判断,方法如下:

public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final MyBag other = (MyBag) obj;
if (books == null) {
if (other.books != null)
return false;
} else if (!books.equals(other.books))
return false;
if (Float.floatToIntBits(money) != Float.floatToIntBits(other.money))
return false;
return true;
}

我们也可以通过实现hashCode()来实现:
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((books == null) ? 0 : books.hashCode());
result = prime * result + Float.floatToIntBits(money);
return result;
}

那么我们判断两个对象对等时,就可以这样来实现了:
if(bag1.equals(bag2)){
// 对等
}

或者
if(bag1.haseCode()==bag2.hashCode()){
// 对等
}

为什么这种方式也能判断两个对象对等呢?
因为,任何一个对象的hashCode是唯一的,并且和气对象属性按照一定的规则相关的。

比如,一个Integer的hashCode值就是其整数值,因为Integer的haseCode()是这样实现的:
public int hashCode() {
return value;
}
public boolean equals(Object obj) {
if (obj instanceof Integer)
return value == ((Integer) obj).intValue();
else
return false;
}

由此可以看到,也对象的HashCode是和其属性有一定的联系,规则和属性的值有一定的联系,这个规则决定了有相同的hashcode,就有两个对象的属性对等。

点赞