JAVA中判断对象是否相等按如下规则:
首先,判断两个对象的hashCode是否相等
如果hashcode不相等,认为两个对象也不相等
如果hashcode相等,则需进一步判断equals运算是否相等
如果equals运算不相等,认为两个对象也不相等
如果equals运算相等,认为两个对象相等
要注意的是equals()和hashcode()这两个方法都是从object类中继承过来的,Object类中,hashcode方法返回值是如何得到请查阅其他文献,equals方法相当于==,是比较对象的引用值是否相等。
public boolean equals(Object obj) {
return (this == obj);
}
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
• 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
• 反射性:x.equals(x)必须返回是“true”。
• 类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。
• 还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
• 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。
以上这五点是重写equals()方法时,必须遵守的准则,如果违反会出现意想不到的结果,请大家一定要遵守。
public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31 * h + val[off++];
}
hash = h;
}
return h;
}
equals()相等的两个对象,hashcode()一定相等;equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。
反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。
public static void main(String args[]){
String s1=new String("pstar");
String s2=new String("pstar");
System.out.println(s1==s2);//false
System.out.println(s1.equals(s2));//true
System.out.println(s1.hashCode());//s1.hashcode()等于s2.hashcode()
System.out.println(s2.hashCode());
Set hashset=new HashSet();
hashset.add(s1);
hashset.add(s2);
Iterator it=hashset.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
false
true
-967303459
-967303459
public class HashSetTest {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add(new Student(1, "zhangsan"));
hs.add(new Student(2, "lisi"));
hs.add(new Student(3, "wangwu"));
hs.add(new Student(1, "zhangsan"));
Iterator it = hs.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
class Student {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
public String toString() {
return num + ":" + name;
}
}
1:zhangsan
1:zhangsan
3:wangwu
2:lisi
那么怎么解决这个问题呢?答案是:在Student类中重新hashcode()和equals()方法。
例如:
class Student {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
public int hashCode() {
return num * name.hashCode();
}
public boolean equals(Object o) {
Student s = (Student) o;
return num == s.num && name.equals(s.name);
}
public String toString() {
return num + ":" + name;
}
}
1:zhangsan
3:wangwu
2:lisi
1) 重点是重写equals,重写hashCode只是为了提高效率
2) 为什么重点是重写equals呢,因为比较对象相等最终是靠equals来判断
3)hash函数性能高,所以重写hashcode方法在equals方法之前先过滤一次,会加速比较过程