我有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中。
有人能解释一下上述情况吗?
答案 0 :(得分:4)
您混淆的基础是身份与平等的概念,以及对于包含元素的集合意味着什么。让我试着解释一下。
假设您在代码中的某个位置执行了此操作:
HashSet<Emp> hs = new HashSet<>();
hs.add(new Emp(32));
在其他地方,您想要查看32岁的员工是否在该集合中。你会怎么做?你可以考虑这个:
boolean isThere = hs.contains(new Emp(32));
您在此处所做的是创建Emp
将32
传递给构造函数的实例,然后将实例传递给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
可以返回年龄本身。