java中的hashcode()和equals()方法

时间:2020-02-23 14:34:49  来源:igfitidea点击:

在本教程中,我们将尝试在Java中了解HashCode()和equals()方法。

这些方法可以在对象类中找到,因此可用于所有Java类。
使用这两种方法,可以从Hashtable,HashMap或者HashSet存储或者检索对象。

  • hashcode()
  • equals()

hashcode()和equals()方法

hashcode():

我们可能知道是否在HashMap中输入了条目,计算了第一个HashCode,并且用于查找桶(索引)的哈希码,此条目将存储在HashMap中。
我们可以在HashMap中的更多信息阅读Java如何阅读。

如果我们不覆盖HashCode方法,它将返回内存地址的整数表示。

equals():

当我们想要在两个对象之间定义平等时,我们必须覆盖等于方法。
如果不覆盖此方法,则会检查参考架构(==):如果键参考是指同一对象

允许覆盖HashCode()和Equals()的默认估算:

我们不必始终覆盖这些方法,但假设我们要根据名称定义国家对象的平等,然后需要覆盖等于方法,如果要覆盖equals方法,则应覆盖HashCode方法。
下面的例子将明确。

让我们在榜样中看到。
我们有一个名为国家/地区的程序

1.Country.java.

package org.igi.theitroad;
 
public class Country {
 
    String name;
    long population;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public long getPopulation() {
        return population;
    }
    public void setPopulation(long population) {
        this.population = population;
    }
    
}

这个国家类有两个基本的属性和人口。

现在创建一个名为"secalitycheckmain.java"的类

package org.igi.theitroad;
 
public class EqualityCheckMain {
 
    /**
     * @author igi mandliya
     */
    public static void main(String[] args) {
        
        Country Netherlands1=new Country();
        Netherlands1.setName("Netherlands");
        Country Netherlands2=new Country();
        Netherlands2.setName("Netherlands");
        System.out.println("Is Netherlands1 is equal to Netherlands2:" +Netherlands1.equals(Netherlands2));
    }
 
}

运行上面的程序时,我们将得到以下输出

Is Netherlands1 is equal to Netherlands2:false

在上面的程序中,我们创建了两个不同的对象,并将其名称属性设置为"荷兰"。

由于引用Netherlands1和Netherlands2都指向不同的对象,因为默认实现等于==的默认情况下,因此等于方法返回FALSE。
在现实生活中,它应该返回真实,因为没有两个国家可以有同一名称。

现在让我们覆盖等于,如果两个国家的名称相同,则返回true。

将此方法添加到国家程序:

@Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Country other = (Country) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

现在再次运行secralitycheckmain.java

我们将获取以下输出:

Is Netherlands1 is equal to Netherlands2:true

现在这是因为如果两个国家/地区有相同的名称,overriden等于方法返回true。

要记住的一件事,等于方法的签名应与上述相同。

让我们在HashMap中放置这个国家对象:

其中我们将使用Country类对象作为key及其首都名称(字符串)作为HashMap中的值。

package org.igi.theitroad;
 
import java.util.HashMap;
import java.util.Iterator;
 
public class HashMapEqualityCheckMain {
 
    /**
     * @author igi Mandliya
     */
    public static void main(String[] args) {
        HashMap<Country,String> countryCapitalMap=new HashMap<Country,String>(); 
        Country Netherlands1=new Country();
        Netherlands1.setName("Netherlands");
        Country Netherlands2=new Country();
        Netherlands2.setName("Netherlands");
 
        countryCapitalMap.put(Netherlands1, "Delhi");
        countryCapitalMap.put(Netherlands2, "Delhi");
 
        Iterator countryCapitalIter=countryCapitalMap.keySet().iterator();
        while(countryCapitalIter.hasNext())
        {
            Country countryObj=countryCapitalIter.next();
            String capital=countryCapitalMap.get(countryObj);
            System.out.println("Capital of "+ countryObj.getName()+"----"+capital);
 
        }
    } 
}

运行上面的程序时,我们将看到以下输出:

Capital of Netherlands----Delhi
Capital of Netherlands----Delhi

现在你必须想知道甚至通过两个对象是等于的,为什么HashMap包含两个键值对而不是一个。
这是因为第一个HashMap使用哈希码来查找该键对象的桶,如果Hashcodes是相同的,那么只能检查等于的方法,因为哈希码以上两个国家对象使用默认散码方法,两者都有不同的内存地址,因此不同的哈希码。

现在,允许覆盖Hashcode方法.DD按照国家类的方法

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

现在再次运行hashmapequalityCheckmain.java

我们将看到以下输出:

Capital of Netherlands----Delhi

所以现在哈希科特对于上面的两个物体荷兰1和荷兰2是相同的,所以两者都将指向相同的桶,现在等于方法将用于比较它们,这将返回其返回。

这就是java doc说的原因"如果我们覆盖了equals()方法,那么我们必须覆盖hashcode()方法"

hashcode()和equals()比较:

equals():

equals方法实现了对非空对象引用的等效关系:

  • 它是反身:对于任何非空参考值x,x.equals(x)应该返回true。
  • 它是对称的:对于任何非空引用值x和y,xequals(y)应该返回true,如果y.equals(x)返回true。
  • 它是传递的:对于任何非空引用值x,y和z,如果xequals(y)返回true和y.equals(z)返回true,则x.equals(z)应该返回true。
  • 它一致:对于任何非空引用值x和y,xqequals(y)的多个调用一直返回true或者一致返回false,不提供在对象上的等于比较中使用的信息不等于对象。
  • 对于任何非空引用值x,x等xequals(null)应返回false。

hashcode():

  • 每当在执行Java应用程序期间在同一对象上才能调用一次,哈希码方法必须一致地返回相同的整数,而不提供在对象上的等于比较中使用的信息。此整数不需要与应用程序的一次执行到另一个执行相同应用程序的执行。
  • 如果根据等式(对象)方法的两个对象相等,则在两个对象中的每一个上调用HashCode方法必须产生相同的整数结果。
  • 如果根据等式(java.lang.object)方法,则两个对象不相等,则在两个对象中的每一个上调用HashCode方法必须产生不同的整数结果。但是,程序员应该知道,为不平等对象产生不同的整数结果可能会提高散列表的性能。

要记住的要点:

  • 如果要覆盖equals方法,那么我们还应该覆盖HashCode()。
  • 如果两个对象相等,则它们必须具有相同的哈希码。
  • 如果两个对象具有相同的哈希码,那么它们可能会或者可能不等于
  • 始终使用相同的属性来生成等于和哈希码,如我们的例子中使用的名称。