这篇文章主要针对HashSet、HashMap存储元素时,对元素要求,使用自定义类需要保证判断是否为同一对象,equals和hashCode都相等才能时同个对象。否则
- 两对象的equals方法相同,但是hashCode不同,那么HashSet就会存放在两个不同位置,那么就与Set规则冲突了(不能出现两个相同元素,这里的相同就是equals)
- 如果两对象hashCode相同,但是equals不同,那么就会采用哈希桶去保存多个对象,使得Hash性能下降
对象相等和是否为同意对象:
首先我们要注意,equals本身实现是为了判断两对象是否相等,但是有时我们需要根据需求使用equals判断两对象中的部分或全部属性是否相同,而非对象是否相同,所以就重写了equals方法。如String就重写了equals方法,根据字符串值判断是否相等,这很符合我们的思考方式,但是一定要注意这时equals就不能判断两个String对象是否为一个对象。如下:
public class equalTest {
public static void main(String[] args) {
String a = new String("x");
String b = new String("x");
System.out.println(a.equals(b));
//输出结果为true,说明a和b字符串相同;
System.out.println(a==b);
//输出为false说明,a,b不是同一个对象
}
}
下图就说明了这个问题,a和b指向的对象值相等,但是a,b指向的对象并不是同一个对象。
所以在我们自定义类的时候,可以根据需求重写equals方法,但是需要注意的是,像HashSet、HashMap这些集合类,如果存储我们的自定义类的对象时。由于这些集合不允许重复元素出现,所以判断元素标准要求equals方法相等并且hashCode方法相等
下面就是,两个不同的对象的equals方法和hashCode方法可能相同,
import java.util.HashSet;
public class Person {
private String name;
private int age;
public Person(String name,int age) {
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
return result;
}
@Override
public boolean equals(Object obj) {
Person other = (Person) obj;
return this.name.equals(other.name);
}
public static void main(String[] args) {
Person xb = new Person("xb", 20);
Person ace = new Person("xb", 22);
Person xiatom = new Person("xiatom", 20);
System.out.println("xb的hashCode:"+xb.hashCode());
System.out.println("ace的hashCode:"+ace.hashCode());
System.out.println("xiatom的hashCode:"+xiatom.hashCode());
System.out.println();
System.out.println("xb与ace是否相同:"+xb.equals(ace));
System.out.println("xb与xiatom是否相同:"+xb.equals(xiatom));
System.out.println("xiatom与ace是否相同:"+xiatom.equals(ace));
System.out.println();
HashSet<Person> p = new HashSet<>();
p.add(xb);
p.add(xiatom);
p.add(ace);
System.out.println("输出HashSet");
for(Person s:p)
System.out.println(s);
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
运行结果如下:
可以看到,xb和ace对象相等,但是同时存到了HashSet集合中,这就出现了问题。
使用自定义类需要保证判断是否为同一对象,equals和hashCode都相等才能时同个对象。否则
1. 两对象的equals方法相同,但是hashCode不同,那么HashSet就会存放在两个不同位置,那么就与Set规则冲突了(不能出现两个相同元素,这里的相同就是equals)
2. 如果两对象hashCode相同,但是equals不同,那么就会采用哈希桶去保存多个对象,使得Hash性能下降