为什么要重写equals,怎么重写equals,重写equals时还必须重写hashcode方法,详解

一、为什么要重写equals?

默认equals在比较两个对象时,是比较他们是否指向同一个地址的(作用跟 == 相同)。

有时,我们希望两个对象只要是某些属性相同就认为他们的equals返回为true。比如:

Student  s1 = new Student(1,"name1");

Student s2 = new Student(1,"name1");
如果不重写equals的话,他们是不相同的,所以我们要重些equals,判断只要他们的id和名字相同equals就为true,在一些集合(set、map)里有时也这样用,集合里的contain也是用equals来比较。
 
二、如何重写equals?
/** 
 *equlas()方法重写实例 
 */  
class User {  
 /** 
  *方法描述:设置name值 
  *输入参数:String name 
  *返回类型:void 
  */  
 public void setName(String name) {  
  this.name = name;  
 }  
  
/** 
  *方法描述:获取name值 
  *输入参数: 
  *返回类型:String 
  */  
 public String getName() {  
   return name;  
 }  
  
/** 
  *方法描述:重写equals()方法 
  *输入参数:Object obj 
  *返回类型:boolean 
  */  
  
public boolean equals(Object obj) {  
 if(this == obj) {  
   return true;  
 }  
 if(null == obj) {  
   return false;  
 }  
 if(getClass() != obj.getClass()) {  
   return false;  
 }  
  
 User user = (User) obj;  
 if(!name.equals(user.name)) {  
  return false;  
 }  
  return true;  
}  
 private String name;  
}  
  
public class EqualsDemo {  
 public static void main(String[] args) {  
  User userA = new User();  
  userA.setName("王明");  
    
  User userB = new User();  
  userB.setName("王明");  
  
  User userC = new User();  
  userC.setName("王亮");  
  
  System.out.println("userA equals userB:" + userA.equals(userB));  
  System.out.println("userA equals userC:" + userA.equals(userC));  
 }  
}  
三、重写equals时还必须重写hashcode方法
1.public boolean equals(Object obj),和hashcode()方法是object对象中的方法。

2.equals与hashcode间的关系是这样的:

1、如果两个对象相同(即用equals比较返回true),那么它们的hashCode值一定要相同;

2、如果两个对象的hashCode相同,它们并不一定相同(即用equals比较返回false)   

即:
(1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true 
(2)当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false

什么是hashcode?
hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同的。

由于为了提高程序的效率才实现了hashcode方法先进行hashcode的比较,如果不同,那没就不必在进行equals的比较了这样就大大减少了equals比较的次数,这对比需要比较的数量很大的效率提高是很明显的,一个很好的例子就是在集合中的使用;我们都知道java中的List集合是有序的,因此是可以重复的,而set集合无序的,因此是不能重复的,那么怎么能保证不能被放入重复的元素呢,但靠equals方法一样比较的话,如果原来集合中以后又10000个元素了,那么放入10001个元素,难道要将前面的所有元素都进行比较,看看是否有重复,这个效率可想而知,因此hashcode就应遇而生了,java就采用了hash表,

利用哈希算法(也叫散列算法),就是将对象数据根据该对象的特征使用特定的算法将其定义到一个地址上,那么在后面定义进来的数据只要看对应的hashcode地址上是否有值,那么就用equals比较,如果没有则直接插入,只要就大大减少了equals的使用次数,执行效率就大大提高了。继续上面的话题,为什么必须要重写hashcode方法,其实简单的说就是为了保证同一个对象,保证在equals相同的情况下hashcode值必定相同,如果重写了equals而未重写hashcode方法,可能就会出现两个没有关系的对象equals相同的(因为equal都是根据对象的特征进行重写的),但hashcode确实不相同的

那么如何保证这一点!!

这样如果我们对一个对象重写了euqals,意思是只要对象的成员变量值都相等那么euqals就等于true,但不重写hashcode,那么我们再new一个新的对象,当原对象.equals(新对象)等于true时,两者的ashcode是不一样,由此将产生了理解的不一致,如在存储散列集合时(如Set类),将会存储了两个值一样的对象,导致混淆,因此,就也需要重写hashcode()







  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值