复习为什么Set集合要重写hashcode和equals方法

【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();
	}
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值