您的位置:首页 > 其它

Hashcode作用以及hash算法的理解

2010-04-15 13:41 246 查看
package com.coll.hash;

import java.util.Collection;
import java.util.HashSet;

/**
* Hashcode的作用,以及hash算法的理解
* 使用HashSet可能会导致内存泄漏的原因
* 内存泄漏: 就是当前内存中已经没有使用这个对象,但它仍然还停在内存中,没有被释放,一直占用着内存空间.
* @author wangdong
*
*
*/
//equals方法默认比较的是否为同一对象的引用.
/*哈希算法: 用来手提高从元素中查找元素的效率,将集合分成若干个区域,每一个对象都可以计算出一个hashCode,
* 可以将hashCode分组,每一组分别对应一个存储区域.根据对象的哈希值,就可以确定对象存储在哪个区域 。
*
* HashSet就是采用合希算法存取对象的集合。
* 它的内部采用了对某个数字n进行取余的方式对哈希码进行分组和划分对象存储区域,Object类中对义了hashCode()方法,用来返回每个Java对象的哈希值,
* 当从HashSet中查找某个对象时,Java系统首先首先调用对象的hashCode()方法获得该对象的哈希码,然后根据哈希码找到对应的区域,然后取出该区域的每个对象
* 使用equals方法进行比较,这样不用遍历集合中所有的对象就可以得到结果。可见HashSet集合有很好的对象检索性能,但是HashSet集合存储的性能要低些。
* 因为向HashSet集合添加对象时,要先计算它的HashCode值和根据这个hashcode来确定这个对象在集合中存放的位置.
* 为了保证一个类的实例对象在HashSet中正常存储,要求这个类的二个实例对象用equals方法比较相等时,他们的hashcode值也必须相等,
* 也就是说 obj1.equals(obj2) ,则要有:obj1.hashCode() == cbj2.hashCode()
*
* 当一个对象被存放到HashSet以后,就不能再修改这个对象的那些参与计算哈希值运算的字段了.否则,对象修改后的哈希值与最初存储进HashSet时的hashcode值不
* 再相等,在这种情况下即使在使用contains()方法使用当前对象去HashSet检索时,也将返回不同对象的结果,这也会导致无法从hashSet()中删除当前对象,从而就导致了内存泄漏
*/

public class HashCodeTest {

/**
* @param args
*/
public static void main(String[] args) {

Collection collSet= new HashSet();
//放入元素时会先判断 是否存在这个对象,如果存在就不会放入(而不是盖了),如果要想放入,则只有先删除那个对象
User user1 = new User("dong",20);
User user2 = new User("wang",20);
User user3 = new User("wangdong",20);
User user4 = new User("dong",20);

System.out.println( user1.getUsername());
collSet.add(user1);
collSet.add(user2);
collSet.add(user3);
collSet.add(user4); //对象1与对象4是不相等的。因为它们的Hashcode值是不相等的
collSet.add(user2); //没有添加,因为已经存在这个对象了。
user1.setAge(33); //改变后hashCode值就变了。
collSet.remove(user1);
System.out.println("HashSet集合的长度为:"+collSet.size());

System.out.println(user1.equals(user4)); //对象用equals比较相等
//如果没有重写hashCode方法,它们不是相等的.因此可能被存放到同一个Set(不同的区域)中
System.out.println(user1.hashCode() == user4.hashCode());

//因为Object类的hashCode()方法不能满足对象存入到Set集合的要求,因为他的返回值是通过对象的内存地址推算出来的,
// 同一个对象在程序运行的过程中的任何时间返回的哈希值都是不变的,所以,只要是两个不同的实例对象,即使它们用equals()方法比较相等,但是它们
// 默认的hashCode()的返回值是不同的,因此只有在重写hashCode方法后才能是相等的.

System.out.println("user2 hashcode : "+ user2.hashCode()+ user2.getUsername().hashCode());
System.out.println("user3 hashcode : "+ user3.hashCode() + user3.getUsername().hashCode());
System.out.println("user4 hashcode : " + user4.hashCode()+ user4.getUsername().hashCode());
System.out.println(user1.hashCode()==user4.hashCode()); //它们的hashcode值是不相等的,所以他们不是相等的。

}
}

class User{

private String userName;
private int age;

public User(String userName, int age){
this.userName = userName;
this.age = age;
}

public String getUsername() {
return userName;
}

public void setAge(int age){
this.age = age;
}

public void setUserName(String userName){
this.userName = userName;
}

/*

public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (age != other.age)
return false;
if (userName == null) {
if (other.userName != null)
return false;
} else if (!userName.equals(other.userName))
return false;
return true;
}

public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result
+ ((userName == null) ? 0 : userName.hashCode());
return result;
}

*/

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: