📜  Java中的 equals() 和 hashCode() 方法

📅  最后修改于: 2022-05-13 01:54:53.559000             🧑  作者: Mango

Java中的 equals() 和 hashCode() 方法

Java.lang.object 定义了两个非常重要的方法:public boolean equals(Object obj) 和 public int hashCode()。

等于()方法

在Java中,equals() 方法用于比较两个对象的相等性。可以通过两种方式比较相等性:

  • 浅比较: equals 方法的默认实现是在Java.lang.Object 类中定义的,它只是检查两个 Object 引用(比如 x 和 y)是否引用同一个 Object。即它检查x == y。由于 Object 类没有定义其状态的数据成员,因此也称为浅比较。
  • 深度比较:假设一个类提供了自己的 equals() 方法实现,以便比较该类的对象和对象的状态。这意味着要相互比较对象的数据成员(即字段)。这种基于数据成员的比较称为深度比较。

句法 :

public boolean equals  (Object obj)

// This method checks if some other Object
// passed to it as an argument is equal to 
// the Object on which it is invoked.

Object 类的 equals() 方法的一些原则:如果某个其他对象等于给定对象,则遵循以下规则:

  • Reflexive :对于任何参考值 a,a.equals(a) 应该返回 true。
  • 对称:对于任何参考值 a 和 b,如果 a.equals(b) 应返回 true,则 b.equals(a) 必须返回 true。
  • 传递性:对于任何参考值 a、b 和 c,如果 a.equals(b) 返回 true 并且 b.equals(c) 返回 true,则 a.equals(c) 应该返回 true。
  • 一致:对于任何参考值 a 和 b,a.equals(b) 的多次调用始终返回 true 或始终返回 false,前提是没有修改对象上 equals 比较中使用的信息。

    注意:对于任何非空引用值 a,a.equals(null) 应该返回 false。

// Java program to illustrate 
// how hashCode() and equals() methods work
import java.io.*;
  
class Geek 
{
      
    public String name;
    public int id;
          
    Geek(String name, int id) 
    {
              
        this.name = name;
        this.id = id;
    }
      
    @Override
    public boolean equals(Object obj)
    {
          
    // checking if both the object references are 
    // referring to the same object.
    if(this == obj)
            return true;
          
        // it checks if the argument is of the 
        // type Geek by comparing the classes 
        // of the passed argument and this object.
        // if(!(obj instanceof Geek)) return false; ---> avoid.
        if(obj == null || obj.getClass()!= this.getClass())
            return false;
          
        // type casting of the argument. 
        Geek geek = (Geek) obj;
          
        // comparing the state of argument with 
        // the state of 'this' Object.
        return (geek.name == this.name && geek.id == this.id);
    }
      
    @Override
    public int hashCode()
    {
          
        // We are returning the Geek_id 
        // as a hashcode value.
        // we can also return some 
        // other calculated value or may
        // be memory address of the 
        // Object on which it is invoked. 
        // it depends on how you implement 
        // hashCode() method.
        return this.id;
    }
      
}
  
//Driver code
class GFG
{
      
    public static void main (String[] args)
    {
      
        // creating the Objects of Geek class.
        Geek g1 = new Geek("aa", 1);
        Geek g2 = new Geek("aa", 1);
          
        // comparing above created Objects.
        if(g1.hashCode() == g2.hashCode())
        {
  
            if(g1.equals(g2))
                System.out.println("Both Objects are equal. ");
            else
                System.out.println("Both Objects are not equal. ");
      
        }
        else
        System.out.println("Both Objects are not equal. "); 
    } 
}

输出:

Both Objects are equal.

在上面的示例中,请参见以下行:

// if(!(obj instanceof Geek)) return false;--> avoid.-->(a)

我们使用了这条线而不是上面的线:

if(obj == null || obj.getClass()!= this.getClass()) return false; --->(y)

在这里,首先我们比较两个对象(即 g1 和 g2)上的哈希码,如果两个对象生成相同的哈希码,这并不意味着它们相等,因为不同对象的哈希码也可以相同,如果它们具有相同id(在这种情况下)。因此,如果两个对象的生成的哈希码值相等,那么我们将这两个对象与它们的状态进行比较,以便我们覆盖类中的 equals(Object) 方法。如果根据 equals(Object) 方法,两个对象具有相同的状态,则它们相等,否则不相等。如果不同的对象生成不同的哈希码值,性能会更好。

原因:引用obj也可以引用Geek子类的Object。 (b) 行确保如果传递的参数是 Geek 子类的对象,它将返回 false。但是,如果instanceof运算符条件发现传递的参数是 Geek 类的子类,则不会返回 false。读取 InstanceOf运算符。

hashCode() 方法

它以整数形式返回哈希码值。 Hashcode 值主要用于基于散列的集合,如 HashMap、HashSet、HashTable……等。这个方法必须在每个覆盖 equals() 方法的类中被覆盖。
句法 :

public int hashCode()

// This method returns the hash code value 
// for the object on which this method is invoked.

hashCode 的一般合约是:

  • 在应用程序执行期间,如果在同一个 Object 上多次调用 hashCode(),则它必须始终返回相同的 Integer 值,前提是没有修改 Object 上的equals(Object)比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,该整数值不必保持相同。
  • 如果两个对象相等,根据equals(Object)方法,那么 hashCode() 方法必须在两个对象的每一个上产生相同的 Integer。
  • 如果两个 Object 不相等,根据equals(Object)方法,这两个 Object 上的 hashCode() 方法产生的 Integer 值不一定是不同的。它可以是相同的,但在两个对象的每一个上生成不同的整数对于提高基于散列的集合(如 HashMap、HashTable 等)的性能更好。

注意:相等的对象必须产生相同的哈希码,只要它们相等,但是不相等的对象不需要产生不同的哈希码。

相关链接:在Java中覆盖相等
参考: JavaRanch