在hash表操作中,hashCode()和equals()方法用于判断两个对象是否相等,在HashSet的contains()方法add()方法、HashMap的contains()方法和put()方法等集合框架中广泛使用。
hashCode()和equals()方法在Object类中被定义,java中任何类都具有这两个方法。在新定义类时,若涉及到新定义类对象的比较,则需要重写这两个方法。
-
如下命题成立
-
命题1:两个对象equals()方法返回true时,hashCode()方法返回值一定相同;
重写equals(Object obj)方法时,有必要重写hashcode()方法,确保通过equals(Object obj)方法判断结果为true的两个对象具备相等的hashcode()返回值。
-
命题1的逆否:两个对象的hashCode()返回值不同,则equals()方法返回值一定false;
-
命题2:两个对象equals()返回值false时,hashCode()方法值可以相等;
- 命题3:两个对象hashCode()相等时,equals()可能为true或false;
所以,在判断两个对象是否相等时,先判断hashCode(),hashCode()不等时直接返回false;hashCode()相等时再判断equals()方法。
-
示例代码
- 由于Object类的hashCode()是将对象的内部地址转换成整数来返回,所以当某个类没有覆盖hashCode()方法时,equals()方法将失败。
import java.util.*;
public class Main1 {
static class Name {
String f = null;
String l = null;
public Name(String f, String l) {
this.f = f;
this.l = l;
}
// 没有重写hashCode()
@Override
public boolean equals(Object obj) {
Name o = (Name)obj;
return this.f.equals(o.f) && this.l.equals(o.l);
}
}
public static void main(String[] args) {
HashSet<Name> set = new HashSet<>();
Name n1 = new Name("pan", "shan");
set.add(n1);
Name n2 = new Name("pan", "shan");
boolean res = set.contains(n2);
System.out.println(res);// false
}
}
同时覆盖equals()和hashCode()方法
import java.util.*;
public class Main1 {
static class Name {
String f = null;
String l = null;
public Name(String f, String l) {
this.f = f;
this.l = l;
}
// 同时重写equals()和hashCode()
@Override
public boolean equals(Object obj) {
Name o = (Name)obj;
return this.f.equals(o.f) && this.l.equals(o.l);
}
@Override
public int hashCode() {
return this.f.hashCode()*31 + this.l.hashCode();
}
}
public static void main(String[] args) {
HashSet<Name> set = new HashSet<>();
Name n1 = new Name("pan", "shan");
set.add(n1);
Name n2 = new Name("pan", "shan");
boolean res = set.contains(n2);
System.out.println(res);// true
}
}