我一直在学习OCJP (前SCJP),我遇到了以下使用LinkedHashSet的示例:
public class Test{
int size;
public Test(int s){
this.size = s;
}
@Override
public boolean equals(Object obj) {
return (this.size == ((Test)obj).size);
}
public static void main(String[] args) {
LinkedHashSet<Test> s = new LinkedHashSet<Test>();
s.add(new Test(1));
s.add(new Test(2));
s.add(new Test(1));
System.out.println(s.size());
}
}现在,问题是如果出现以下情况,将显示什么:
1)实现保持不变
2)在类测试中插入hashCode的覆盖,如下所示:
public int hashCode() {return size/5};运行和编译代码时发现,第一种情况下set的大小为3,而第二种情况下为2。为什么?
在第一种情况下,尽管equals方法被覆盖,但它从未被调用过。这是否意味着如果hashCode方法没有被覆盖,add()方法就不会检查对象相等性?
在情况2中,具有给定实现和给定测试对象集的hashCode总是返回相同的数字。这与默认的hashCode实现有什么不同,为什么它会导致调用equals?
发布于 2012-10-22 03:55:23
如果您不覆盖hashCode(),那么您的每个实例都将具有根据Object类中的一些预定义散列算法计算的散列码。因此,您的所有实例都可能具有不同的hashcode值(但这并不确定)。意味着,每个实例都会进入自己的存储桶中。
现在,即使你重写了equals()方法,使两个实例基于某个属性相等,它们的哈希码仍然是不同的。
因此,具有不同哈希码的两个实例永远不可能相等。因此集合的大小是3。因为它没有任何重复项。
但是,当您使用以下实现覆盖hashCode()时:
public int hashCode() {return size/5};它将为相同的size返回相同的值。因此,具有相同size值的实例将具有相同的哈希码,而且,由于您已经在基于size的equals方法中对它们进行了比较,因此它们将是equal,因此它们在您的Set中将被视为重复,因此将被视为removed.So,Set.size()为2。
道德:当你重写hashCode()方法时,你应该总是重写equals()方法,以维护两个方法之间的一般契约。
hashcode equals 和method之间的总合同:-
same attributes计算您用来比较两个实例的hashCode F241
强烈建议至少读一次:-
发布于 2012-10-22 03:57:01
散列结构依赖于散列算法,该算法在java中由hashCode()表示。当您将某些内容放入HashMap (在本例中为LinkedHashSet )中时,jvm将在插入到此结构中的对象上调用hashCode()。当它没有被覆盖时,将使用来自Object类的默认hashCode(),这是非常低效的--所有的对象都进入它们自己的存储桶中。
当您按照示例中所示的方式覆盖hashCode()时,示例中的所有对象都将进入同一个存储桶中。然后(当一个接一个地添加它们时),与equals()进行比较。这就是为什么在第一种情况下(不调用equals()时)得到的大小为3,而在第二种情况下得到的大小是2。
https://stackoverflow.com/questions/13001568
复制相似问题