Java中equals,hashcode

本文详细解析了Java中Object类的equals与hashCode方法的工作原理,包括它们如何在Integer类中被重写,以及如何正确地在自定义类中实现这两个方法以确保数据结构如HashMap的高效运行。

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

     在Java语言中,Object对象中包含一个equals和hashCode方法,其中hashCode方法是由JVM本地代码(native code)实现的,返回值是一个 有符号的32位整数,对象的hash值一般为用于在管理多个对象的数据结构中 用于提高性能而设计的,比如HashMap。有些语言的hash值就是这个对象在内存中的地址转化的整数, 但是java中的实现并不是这样。equals方法的实现很简单,就是利用==运算符比较两个对象的内存引用地址是否相等,当然,不是所有对象的比较都是比较内存,比如Integer,Long,Double等这些表示数字的类内部都对equals方法进行了重写,这些数值类equals比较的是数值大小。
 
Object类的equals&hashCode的实现:
public boolean equals(Object obj) {
     return (this == obj);
}
 
public native int hashCode();
Integer类的内部equals和hashCode的实现:
public boolean equals(Object obj) {
       if (obj instanceof Integer) {
           return value == ((Integer)obj).intValue();
      }
       return false;
    }
 
     public int hashCode () {
       return value;
    }

关于hash值的一般性规约

  • 对同一个对象多次调用hashCode方法,都应该始终如一的返回同一个值
  • 对象相等,其hash值比较也应该相等(如果重写了对象的equals方法,那么对应的hashCode的实现也应该要重写以保证hash值也是相等的)
  • 对象不等,其hash值不要求也不等(但如果能不等,会提高程序性能)。
重写HashCode()和equals()
 
Employee e1 = new Employee();
Employee e2 = new Employee();
 
e1.setId(100);
e2.setId(100);
//Prints false in console
System.out.println(e1.equals(e2)); // output: false
对于上面的代码,在具体的业务逻辑中我们通常希望比较的结果应该是:true,但是由于两个对象引用的地址不同,所以equals比较的结果是false,若希望e1和e2比较的结果是true,我们就需要重写equals方法
@override
public boolean equals(object o) {
 
        if(o == null)        {
 
            return false;
        }
        if (o == this)
        {
          return true;
        }
        if (getClass() != o.getClass())
        {
            return false;
        }
        Employee e = (Employee) o;
        return (this.getId() == e.getId());
}

 再看下面的例子:

Set<Employee> employees = new HashSet<Employee>();
        employees.add(e1);
        employees.add(e2);
        System.out.println(employees); // output: two elements

 我们期望的结果是:若equals比较相等的对象,放入HashSet或HashMap中也应该只能放入一个,但为什么会出现两个元素呢,因为两个对象的hashCode值是不一样的,所以HashSet认为是两个不同的元素。因此,若想得到期望的结果,需要重写hashCode方法:

 
@Override
public int hashCode()
{
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
}

 

利用Eclipse的代码生成工具生成重写HashCode和equals的方法

 
生成的代码如下:
@Override
public int hashCode() {
             final int prime = 31;  // 见参考文章
             int result = 1;
            result = prime * result + age ;
            result = prime * result + (( name == null ) ? 0 : name .hashCode());
             return result;
      }
       @Override
       public boolean equals(Object obj) {
             if (this == obj)
                   return true ;
             if (obj == null)
                   return false ;
             if (getClass() != obj.getClass())
                   return false ;
            HashCodeDemo1 other = (HashCodeDemo1) obj;
             if (age != other. age)
                   return false ;
             if (name == null) {
                   if (other.name != null)
                         return false ;
            } else if (! name.equals(other. name ))
                   return false ;
             return true ;
      }

注意事项:

  • equals和hashCode方法一般需要同时重写
  • 如果a.equals(b),那么也要保证a.hashCode() == b.hashCode()
  • 尽量使用相同的属性来重写equals和hashCode方法,比如上述例子中两个重写方法中都是利用的id属性。
  • 如果你使用ORM处理一些对象的话,你要确保在hashCode()和equals()对象中使用getter和setter而不是直接引用成员变量。因为在ORM中有的时候成员变量会被延时加载,这些变量只有当getter方法被调用的时候才真正可用。
参考:

转载于:https://www.cnblogs.com/ktgu/p/3529138.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值