【wo yao hua li hu shao】
如果不重写hashCode,自定义的类,生成两个形参一样的对象,其生成的哈希值是不一样的。即两个对象的内容是一样的,但是它们的哈希值却不一样。
因为哈希值是根据地址计算的,而new出来的空间是在堆中存放的,两个new就会有两个堆地址,所以它们的哈希值不一样
一、自定义四个类
1.没有重写hashcode方法和equals方法的A类
//1.没有重写hashcode方法和equals方法 class A{ int i ; public A(int i){ this.i = i; } public String toString(){ return "A"; } }
2.只重写hashcode方法的B类
//2.只重写hashcode方法 class B{ int i ; public B(int i){ this.i = i; } public String toString(){ return "B"; } @Override public int hashCode(){ return new Integer(i).hashCode(); } }
3.只重写equals方法的C类
//3.只重写equals方法 class C{ int i ; public C(int i){ this.i = i; } public String toString(){ return "C"; } @Override public boolean equals(Object mm){//这里的形参必须是Object类型不然无法重写该方法 C cc = (C)mm;//再使用强转,用cc接收即可 return this.i == cc.i; } }
4.重写hashcode方法和equals方法的D类
//4.重写hashcode方法和equals方法
class D{
int i ;
public D(int i){
this.i = i;
}
public String toString(){
return "D";
}
@Override
public boolean equals(Object nn){
D dd = (D)nn;
return this.i == dd.i;
}
@Override
public int hashCode(){
return new Integer(i).hashCode();
}
}
二、测试四个类
这里生成了HashSet对象,后面的添加都是用的它
Set s = new HashSet();
//Set集合的元素应该是无序且不重复的
//Set集合是先判断哈希值是否相同,再判断equals方法的,但是如果哈希值相同就不再执行equals方法
//但大多数情况下,new出来的空间,虽然存放的内容一样,但地址是不一样的,就会导致哈希值不一样
1.测试---没有重写hashcode方法和equals方法的A类
//1. 没有重写hashcode方法和equals方法 A aa = new A(12); A ab = new A(12); System.out.println(aa.hashCode()); System.out.println(ab.hashCode());//两个不同对象,相同的形参,但是哈希值是不一样的 //Set集合的元素应该是无序且不重复的 //Set集合是先判断哈希值是否相同,再判断equals方法的,但是如果哈希值相同就不再执行equals方法 //但大多数情况下,new出来的空间,虽然存放的内容一样,但地址是不一样的,就会导致哈希值不一样 s.add(aa); s.add(ab); //System.out.println(s);//但这里,内容相同的两个都存进去了,这是因为它们的哈希值是不同的
2.测试---只重写hashcode方法的B类
//2.只重写hashcode方法,此时虽然它们的哈希值一样了,但是set集合会转去执行equals方法 //因为默认的equals方法也是判断两者的地址的,所以这里,因为是不同的堆地址,equals方法会认为它们不相等,尽管内容一样,但是它们地址不一样 B bb = new B(13); B bc = new B(13); s.add(bb); s.add(bc); //System.out.println(s);//但这里,内容相同的两个都存进去了,这是因为它们的哈希值一样,但是堆地址确是不同的
3.测试---只重写equals方法的C类
//3.只重写equals方法,也会导致set集合元素重复。因为set是先判断哈希值的,再判断equals的,如果哈希值不相同,set会认为已经找到了答案,就不再执行equals了 C cc = new C(14); C cd = new C(14); s.add(cc); s.add(cd); //System.out.println(s);//但这里,内容相同的两个都存进去了,这是因为先判断的两者哈希值,而哈希值显然是不一样的,所以set认为它们不一样
4.测试---重写hashcode方法和equals方法的D类
//4.重写hashcode方法和equals方法
D dd = new D(15);
D df = new D(15);
s.add(dd);
s.add(df);
System.out.println(s);//set集合中只有一个D,成功!
✌留个纪念---全的~
import java.util.*;
class Demo{
public static void main(String[] args){
/*
如果不重写hashCode,自定义的类,定义了两个形参一样的对象,其生成的哈希值是不一样
即两个对象的内容是一样的,但是它们的哈希值却不一样。因为哈希值是根据地址计算的,而new出来的空
间是在堆中存放的,两个new就会有两个堆地址,所以它们的哈希值不一样
*/
//1. 没有重写hashcode方法和equals方法
A aa = new A(12);
A ab = new A(12);
System.out.println(aa.hashCode());
System.out.println(ab.hashCode());//两个不同对象,相同的形参,但是哈希值是不一样的
//Set集合的元素应该是无序且不重复的
//Set集合是先判断哈希值是否相同,再判断equals方法的,但是如果哈希值相同就不再执行equals方法
//但大多数情况下,new出来的空间,虽然存放的内容一样,但地址是不一样的,就会导致哈希值不一样
Set s = new HashSet();
s.add(aa);
s.add(ab);
//System.out.println(s);//但这里,内容相同的两个都存进去了,这是因为它们的哈希值是不同的
//2.只重写hashcode方法,此时虽然它们的哈希值一样了,但是set集合会转去执行equals方法
//因为默认的equals方法也是判断两者的地址的,所以这里,因为是不同的堆地址,equals方法会认为它们不相等,尽管内容一样,但是它们地址不一样
B bb = new B(13);
B bc = new B(13);
s.add(bb);
s.add(bc);
//System.out.println(s);//但这里,内容相同的两个都存进去了,这是因为它们的哈希值一样,但是堆地址确是不同的
//3.只重写equals方法,也会导致set集合元素重复。因为set是先判断哈希值的,再判断equals的,如果哈希值不相同,set会认为已经找到了答案,就不再执行equals了
C cc = new C(14);
C cd = new C(14);
s.add(cc);
s.add(cd);
//System.out.println(s);//但这里,内容相同的两个都存进去了,这是因为先判断的两者哈希值,而哈希值显然是不一样的,所以set认为它们不一样
//4.重写hashcode方法和equals方法
D dd = new D(15);
D df = new D(15);
s.add(dd);
s.add(df);
System.out.println(s);//set集合中只有一个D,成功!
}
}
//1.没有重写hashcode方法和equals方法
class A{
int i ;
public A(int i){
this.i = i;
}
public String toString(){
return "A";
}
}
//2.重写hashcode方法
class B{
int i ;
public B(int i){
this.i = i;
}
public String toString(){
return "B";
}
@Override
public int hashCode(){
return new Integer(i).hashCode();
}
}
//3.重写equals方法
class C{
int i ;
public C(int i){
this.i = i;
}
public String toString(){
return "C";
}
@Override
public boolean equals(Object mm){//这里的形参必须是Object类型不然无法重写该方法
C cc = (C)mm;//再使用强转,用cc接收即可
return this.i == cc.i;
}
}
//4.重写hashcode方法和equals方法
class D{
int i ;
public D(int i){
this.i = i;
}
public String toString(){
return "D";
}
@Override
public boolean equals(Object nn){
D dd = (D)nn;
return this.i == dd.i;
}
@Override
public int hashCode(){
return new Integer(i).hashCode();
}
}