equals()与hashCode()方法总结
1.hashCode方法的作用:
对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。
2.改写equals时总是要改写hashCode
下面这段话摘自Effective Java一书:
1.在程序执行期间,只要equals方法的比较操作用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法必须始终如一地返回同一个整数。
2.如果两个对象根据equals方法比较是相等的,那么调用两个对象的hashCode方法必须返回相同的整数结果。
3.如果两个对象根据equals方法比较是不等的,则hashCode方法不一定得返回不同的整数。
在《Java编程思想》一书中提到过这样的话:设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用 hashCode()都应该产生同样的值。如果在讲一个对象用put()添加进HashMap时产生一个hashCdoe值,而用get()取出时却产生 了另一个hashCode值,那么就无法获取该对象了。所以如果你的hashCode方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化 时,hashCode()方法就会生成一个不同的散列码
3.hashCode对某些集合的影响
package test;
import java.util.HashSet;
import java.util.Set;
class A{
private String name;
private int age;
A(String name,int age){
this.name=name;
this.age=age;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(obj instanceof A){
A a=(A) obj;
if(name.equals(a.getName())&&age==a.getAge()){
return true;
}
}
return false;
}
@Override
public int hashCode() {
return age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
}
public class HashCodeTest {
public static void main(String[] args) {
A a=new A("jiajia",1);
A a2=new A("wanghusai",1);
Set<A> set=new HashSet<A>();
set.add(a);
set.add(a2);
System.out.print(set.size()+"-");
a2.setAge(2);
set.add(a2);
System.out.println(set.size());
}
}
重写hashCode方法为:
@Override
public int hashCode() {
return age;
}
结果是:2-3
改变a2.age后HashSet无法找到a2这个对象了,可见覆写hahcode对HashSet的存储和查询造成了影响
如果重写的Hashcode方法如下:
@Override
public int hashCode() {
return name.hashCode();
}
那么结果为:2-2
这一点体现在:在一个应用程序运行期间,假设一个对象的equals方法做比較所用到的信息没有被改动的话。则对该对象调用hashCode方法多次,它必须始终如一地返回同一个整数。
如果只重写equals方法而不重写hashCode方法的时候:
package test;
import java.util.HashSet;
import java.util.Set;
class A{
private String name;
private int age;
A(String name,int age){
this.name=name;
this.age=age;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(obj instanceof A){
A a=(A) obj;
if(name.equals(a.getName())&&age==a.getAge()){
return true;
}
}
return false;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
}
public class HashCodeTest {
public static void main(String[] args) {
A a=new A("jiajia",1);
A a2=new A("jiajia",1);
Set<A> set=new HashSet<A>();
set.add(a);
set.add(a2);
System.out.print(set.size()+"-");
}
}
我们认为a,和a2是同一个对象,但是还是能添加进set集合,但是实际上两对象在内存中不是同一个对象,hash值是不同的。
所以:如果两个对象根据equals方法比较是相等的,那么调用两个对象的hashCode方法必须返回相同的整数结果。
总结无论何时:
对同一个对象调用hashcode()都应该生成同样的值。
重写equals方法的时候应该同时重写hashCode方法。
hashcode()尽量使用对象内有意义的识别信息。
好的hashcode()应该产生分布均匀的散列值。