1、这两个方法都是object根类的方法
2、equal在object类里,比较的就是hashcode散列码; 而hashcode方法在object类里,返回的是对象的地址。
但是在常用的JDK里的类中,比如string,都会重写这两个方法,即不同的类会有不同的hashcode计算方法和equal方法(当然在string类里比较的还是hashcode)。
3、当有自定义类时,如果仅仅用来比较两个类,可以只重写equal方法。
但是,当和容器联系在一起时,比如map、set。要知道,像hashset这种容器,就是把hashmap中的key作为对应存储项的。而且并不是存储对象本身,而是对象的hashcode,存储hash散列码的好处是便于查询。
在java的集合中,判断两个对象是否相等的规则是:
1,判断两个对象的hashCode是否相等
如果不相等,认为两个对象也不相等,完毕
如果相等,转入2
2,判断两个对象用equals运算是否相等
如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等
综上所述,equal和hashcode两个方法,既独立又有关系。举个例子:
package com.yj.testequal;public class MyString {String mStr;int mHashCode;public MyString(String s, int hashcode) {mStr = s;mHashCode = hashcode;}@Overridepublic int hashCode() {return mHashCode;}@Overridepublic boolean equals(Object obj) {if(! (obj instanceof MyString))return false;return mStr.equals(((MyString)obj).mStr);}}
package com.yj.testequal;
import java.util.HashSet;
import java.util.Set;
public class TestEqual {
/**
* @param args
*/
public static void main(String[] args) {
MyString m1 = new MyString("fuck1", 123);
MyString m2 = new MyString("fuck2", 2344);
System.out.println(m1.hashCode());
System.out.println(m2.hashCode());
System.out.println(m1.equals(m2));
MyString m3 = new MyString("fuck12", 123);
System.out.println(m1.equals(m3));
Set<MyString> sms = new HashSet<MyString>();
sms.add(m1);
sms.add(m2);
if(sms.contains(m3)) {
System.out.println("contains");
} else {
System.out.println("not contains");
}
}
}
在分别添加了m1和m2后,新建一个对象m3,无论单独让m3的hashcode返回值和m1一样,还是单独让equal返回值一样,在set里都不认为这两个是同一个对象;只有hashcode和equal方法的返回值都相同,才会认为是同一对象。
再说一下为什么集合里要这么比较吧,因为如果集合数量非常大的时候,散列函数会有冲突,就是不同的键可能产生相同的下标;如果hashcode相同的话,就要继续比较equal喽。比较equal方法时就是线性查询了。
注:完美的散列函数在Java SE5的EnumMap和EnumSet中得到了实现。