equals 和 hashcode 的关系,Object.equals 默认比较的是地址

本文解释了在重写equals方法时为何通常也需要重写hashCode方法,通过实例代码演示了hashCode的作用,及其如何影响HashSet等集合类的性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在重写一个类的equals()的同时,一般要重写hashCode()除非你确认类的对象不会放入HashSet,HashTable,HashMap。 
那么为什么要重写hashCode()呢?主要是为了确保hash表里面不会被放入重复的对象,以提高性能。那为什么重写了hashCode()就可以做到这一点呢?下面以一段代码分析。 
Java代码  收藏代码
  1. /**Strudent重写了equals和hashCode,这里假设只要学号相等则是同一个对象。 
  2.    先看看hashCode()返回相同的值:0的情况。 
  3. */  
  4. public class Student {  
  5.     public Student(String no) {  
  6.         this.no = no;  
  7.     }  
  8.     //永远都返回0  
  9.     @Override  
  10.     public int hashCode() {  
  11.         System.out.println("call hashcode");  
  12.         return 0;  
  13.     }  
  14.   
  15.     // 这里的equals实现学号相同表示相等  
  16.     @Override  
  17.     public boolean equals(Object obj) {  
  18.         System.out.println("call equals");  
  19.         if (this == obj)  
  20.             return true;  
  21.         if (getClass() != obj.getClass())  
  22.             return false;  
  23.         Student other = (Student) obj;  
  24.         if (no == null) {  
  25.             if (other.no != null)  
  26.                 return false;  
  27.         } else if (!no.equals(other.no))  
  28.             return false;  
  29.         return true;  
  30.     }  
  31.   
  32.     // 学号,假设必须唯一  
  33.     private String no;  
  34.     private String name;  
  35.   
  36.     public String getNo() {  
  37.         return no;  
  38.     }  
  39.   
  40.     public void setNo(String no) {  
  41.         this.no = no;  
  42.     }  
  43.   
  44.     public String getName() {  
  45.         return name;  
  46.     }  
  47.   
  48.     public void setName(String name) {  
  49.         this.name = name;  
  50.     }  
  51. }  

Java代码  收藏代码
  1. public class Main {  
  2.     public static void main(String[] args) {  
  3.         Set<Student> set = new HashSet<Student>();  
  4.         set.add(new Student("1"));  
  5.         System.out.println("----------");  
  6.         set.add(new Student("2"));  
  7.         System.out.println("----------");  
  8.         set.add(new Student("3"));  
  9.         System.out.println("----------");  
  10.         System.out.println(set.size());  
  11.     }  
  12. }  

我们看看输出结果: 
Java代码  收藏代码
  1. call hashcode  
  2. ----------  
  3. call hashcode  
  4. call equals  
  5. ----------  
  6. call hashcode  
  7. call equals  
  8. call equals  
  9. ----------  
  10. 3  


看到了吗?呵呵,就是每次在往Set里add(object)时,先调用hashCode(),若hash码与set里面某个object的hash码不相等,则直接放入set;否则调用equals(object),若与set中某个object相等(即hashCode相等,而且equals返回true),则返回,不放入set,否则放入set。 

再来看看这样重写hashCode时的结果: 
Java代码  收藏代码
  1. //这里返回学号的hashCode。  
  2. @Override  
  3. public int hashCode() {  
  4.     System.out.println("call hashcode");  
  5.     return no.hashCode();  
  6. }  

再运行一下,结果如下: 
Java代码  收藏代码
  1. call hashcode  
  2. ----------  
  3. call hashcode  
  4. ----------  
  5. call hashcode  
  6. ----------  
  7. 3  


也就是说学号不同(各个object的hashCode不同),直接放入Set,没有执行equals。 

总结:重写equals的时候,一般要重写hashCode,并尽量保证不同object的hashCode不同,以提高hash的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值