咸糖记录编程的地方

念念不忘,必有回响。

目录
equals() 和 hashCode() 方法在Java中的关系
/  

equals() 和 hashCode() 方法在Java中的关系

Java.lang.object 定义了两个非常重要的方法:

  • public boolean equals(Object obj)
  • public int hashCode()

equals() 方法

在Java 中 equals()是用来比较两个对象是否相等。主要分为两个方面的比较:

  • 浅比较(Shallow comparison):在Java.lang.Object 类中默认的实现是简单的比较两个引用(假设是x和y)是否指向同样的对象。由于Object类没有定义其状态的数据成员,所以也称之为浅比较(Shallow comparison)。
  • 深比较(Deep Comparison):假设一个类提供了拥有对equals()方法的自己的实现,目的去比较具有w.r.t状态的对象。意思是对象中的数据成员(例如:域)将会被比较。基于数据成员的比较方式叫做深比较(Deep Comparison)。

语法:

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
//作为参数传递给它等于
//调用它的Object。

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

  • Reflexive:对于任何引用a,a.equals(a)应该返回true。
  • Symmetric:对于任何引用a和b,如果a.equals(b)返回true,那么b.equals(a)必须返回true。
  • Transitive:对于任何引用a,b和c,如果a.equals(b)返回true, 并且b.equals(c)返回true,则a.equals(c)应该返回true。
  • Consistent:对于任何应用a和b,多次调用a.equals(b)始终返回true或始终返回false,前提是在没有修改对象equals比较中使用的信息。

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

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() 
    { 
        // 我们返回Geek_id作为hashcode
        // 我们可以计算或者使用对象内存地址的值
        // 这取决于你如何实现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.

首先我们比较hashCode在两个对象上(g1和g2)如果hashCode产生自两个对象并不意味着这两个对象相同,两个不同的对象的hashCode也是可以相同的。而且,如果他们拥有相同的id(在这种情况下)。那么我们将比较这两个对象w.r.t的状态。如果两个对象具有相同的状态,则他们相等,否则不相等。

在上面的例子中看到这一行:

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

我们使用下面一行来代替上面这一行:

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

原因:引用obj也可以引用Geek对象的子类,在Line(b)中传入的对象是Geek的子类的对象的话,就会返回false,但是在Line(a)中却会返回true。

hashCode() method

它将哈希码值作为整数返回。 Hashcode值主要用于基于散列的集合,如HashMapHashSetHashTable … .etc。必须在覆盖equals()方法的每个类中重写此方法。

语法:

public int hashCode()

// This method returns the hash code value 
// for the object on which this method is invoked.
// 当这个方法被调用时候返回hashcode

普遍的hashCode规定有:
* 在代码的运行期时,多次调用hashCode()在同一个对象然后必须返回一致的整数值。如果对象没有在equals(ojb)比较中有成员变量被修改,调用后返回的值都一致。
* 如果两个对象相等,则根据equals(Object)方法,hashCode()方法必须在两个对象中的每一个上生成相同的Integer。
* 如果两个对象不相等,则根据equals(Object)方法,hashCode()方法在两个对象中的每一个上生成的Integer值不必是不同的。它可以是相同的,但是对于两个不同的对象,通过hashCode产生不同的值对于提高基于散列的集合(如HashMap,HashTable等)的性能会更好。


标题:equals() 和 hashCode() 方法在Java中的关系
作者:xiantang
地址:http://xiantang.info/articles/2019/06/03/1559551200545.html

评论