Java重写equals方法和hashCode方法
今天在学习HashSet集合时,遇到当从HashSet中插入和删除元素时,HashSet集合都要先调用hashCode方法计算元素的哈希值,然后再调用equals方法。
- 当向HashSet中添加元素时:每次添加元素都会调用hashcode方法,而只有当hashcode一样时才会调用equals方法。
说明,在插入元素时会首先调用hashcode方法来判断有无重复,如果没有直接插入,如果有则去比较hashcode重复的对象的equals方法,看equals是否重复,如果equals一样,不会插入,如果equals不一样,则插入。 - 当向HashSet中删除元素时: 调用hashcode方法计算出哈希值从而确定要删除元素的位置,然后用equals对象进行比较,若返回true,则删除元素
但是当你向HashSet中添加了可变元素并试图改变该元素的值时,HashSet集合的删除操作就会变得十分混乱
import java.util.HashSet;
import java.util.Iterator;
public class HashSetTest {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add(new R(-3));
hs.add(new R(5));
hs.add(new R(9));
hs.add(new R(-2));
//打印HashSet集合,集合元素没有重复
System.out.println(hs);
//取出第一个元素
Iterator it = hs.iterator();
R first = (R) it.next();
//为第一个元素的count实例变量赋值
first.count = -3;
System.out.println(hs);
hs.remove(new R(-3));
System.out.println(hs);
System.out.println("hs是否包含count为-3的对象? " + hs.contains(new R(-3)));
System.out.println("hs是否包含count为-2的R对象? " + hs.contains(new R(-2)));
}
}
class R{
int count;
public R(int count){
this.count=count;
}
public String toString(){
return "R[count:" + count + "]";
}
public boolean equals(Object obj){
/*if(this==obj)
return true;
if (obj!=null && obj.getClass()==R.class){
R r=(R)obj;
return this.count==r.count;
}
return false;*/
if (obj instanceof R) {
R r = (R)obj;
if (r.count == this.count) {
return true;
}
}
return false;
}
public int hashCode(){
return this.count;
}
}
-
上面程序创建了一个HashSet
-
修改集合中第一个槽的count<因重写了hashcode方法,count值即hashcode值>值
-
接着删除count值为-3的元素
虽然集合中有两个元素count值为-3,但删除的是位于第二个槽位的元素
<调用hashcode方法确定要删除元素位于一二槽位,接着调用equals方法,确定为第二槽位>
注意此程序中equals方法的重写,有两种写法,第一种写法的第一个if用来检测是否为同一对象,第二个if用来比较当对象不同时,其属性是否相同(我们重写规定在不是同一对象的情况下,count值相当也返回true)
-
结果
很明显出现了混乱,当我们删除了第二槽位的元素后,现在寻找集合中count值为-3的元素,没找到;寻找集合中为-2的元素,也没找到。
现在是第一槽位count值为-2却保存着count值为-3的对象,所以发生错误
说了这么多废话,其实也就是HashSet里不能添加重复元素,也尽量不要添加可变元素