什么时候我需要hashcode和equals方法?

时间:2017-01-12 05:49:25

标签: java

我有hashset whare我将设置存储到对象,我想找到特定的对象,在这种情况下为什么我需要覆盖我从下面的例子中读取的hashcode和equals方法

public class Emp 
{
    private int age ;

    public Emp( int age )
    {
        super();
        this.age = age;
    }

    public int hashCode()
    {
        return age;
    }

    public boolean equals( Object obj )
    {
        boolean flag = false;
        Emp emp = ( Emp )obj;
        if( emp.age == age )
            flag = true;
        return flag;
    }
}

他们说如果我没有覆盖hashcode和equals方法,我会因下面的查询而变错。

System.out.println("HashSet Size--->>>"+hs.size());
System.out.println("hs.contains( new Emp(25))--->>>"+hs.contains(new Emp(25)));
System.out.println("hs.remove( new Emp(24)--->>>"+hs.remove( new Emp(24));
System.out.println("Now HashSet Size--->>>"+hs.size());

我混淆了这与hashcode有什么关系,等于只检查contains(anyobject)和remove(anyobject)在hashset中。

有人能解释一下上述情况吗?

1 个答案:

答案 0 :(得分:4)

您混淆的基础是身份与平等的概念,以及对于包含元素的集合意味着什么。让我试着解释一下。

假设您在代码中的某个位置执行了此操作:

HashSet<Emp> hs = new HashSet<>();
hs.add(new Emp(32));

在其他地方,您想要查看32岁的员工是否在该集合中。你会怎么做?你可以考虑这个:

boolean isThere = hs.contains(new Emp(32));

您在此处所做的是创建Emp32传递给构造函数的实例,然后将实例传递给contain()

请注意,此实例与您添加到集合时创建的实例不同。所以,问题是:contains()应该返回true,因为这个实例与你添加的实例相同,或者它应该返回false,因为它不是同一个实例?

结果取决于hashCode()的{​​{1}}和equals()的实施方式。使用默认实现时,Emp仅在传递的实例与包含的实例完全相同时返回true(即使用equals()来比较传递给==的实例和存储的实例)。在这种情况下,它将返回contains()

要了解false,您需要了解hashCode()的工作原理。 向HashSet添加元素时,使用HashSet从元素计算数组中的索引。然后将该元素设置为相应索引处的值。

由于不同的元素可能最终具有相同的hashCode() % <size of the array>,因此可以在同一索引处映射更多元素,在这种情况下,保持冲突列表。

那么,回到你的案例,你为什么需要实施hashCode()?因为默认实现将为hashCode()的不同实例返回不同的数字,但事件虽然Ent可能相同(实现依赖于JVM,例如它可以返回实例的内存中的地址)。因此,要使包含起作用,我们需要确保为这两个实例计算数组中的相同索引,因此您需要相应地实现它。例如,在这种情况下,age可以返回年龄本身。