hashCode的作用是为了提高查找效率,new出来的对象被放到hash表中,提取对象的时候就会根据hashCode去表中提取,这样提高了提取对象的效率。
具体过程是这样:
1.new Object(),JVM根据这个对象的Hashcode值,放入到对应的Hash表对应的Key上,如果不同的对象确产生了相同的hash值,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同hashcode的对象放到这个单链表上去,串在一起。
2.比较两个对象的时候,首先根据他们的hashcode去hash表中找他的对象,当两个对象的hashcode相同,那么就是说他们这两个对象放在Hash表中的同一个key上,那么他们一定在这个key上的链表上。那么此时就只能根据Object的equal方法来比较这个对象是否equal。当两个对象的hashcode不同的话,肯定他们不能equal.
下面我通过set存取对象对hashCode进行说明。
1. Set存储对象的规则是无序不重复。
2. 下面我通过代码来说明hashCode的使用
calss TestHashCode{
public static void main(String[] args){
Code c1= new Code(1);
Code c2= new Code(2);
Set set = new HashSet();
set.add(c1 set.add(c2);
set.add(c1);
set.add(c System.out.println("now is"+set.size());
c2.i=1;
//因为重写了equals方法所以这里为true
System.out.println(c1.equals(c2));
/*set集合添加元素时会根据元素的hashcode生成散列表,散列表一 旦生成就不会再改变,并且set会通过元素的hashcode到散列表中查找元素,所以此时根据c2的hashCode找到的是c1,然后用c2.equals(c1)判断是否为同一对象,由于我们改写了equals方法导致c1 和c2为同一对象,此时set将c1移除,size变为1,如果将Code Class中的equals方法注释,根据hashCode找到c1,发现c2,c1不为同一对象,此时set.remove(c2)将找不到移除的元素,不能移除,size仍为2*/
set.remove(c2);
System.out.println("now is"+set.size());
}
}
class Code{
int i;
public Code(int i){
this.i = i;
}
@Override
public boolean equals(Object o){
if(!(o instanceof Code))
return false;
return ((Code)o).i==this.i;
}
@Override
public int hashCode(){
return i;
}
}
总结:hash表中在放置元素时,先通过hashCode决定存贮的位置,如果hashCode不同,不管对象是否equals就放置在不同位置,如果hashCode相等,对象不equals,就在该位置产生链表,将两个对象都存贮,如果hashCode和equals都相等,则保留旧对象,新对象不再存贮。所以set中可以存在hash码不同的相同(equals)对象。当然,hashCode 方法的常规协定声明相等对象必须具有相等的哈希码(尽管很多时候不是这样),如果那样就set中同一个对象就只能存一个。
部分引用来自(该博文对hashCode有更详细的描述):
http://blog.csdn.net/chinayuan/archive/2008/11/21/3345559.aspx