假设我有以下课程。
class S{
String txt = null;
S(String i){
txt=i;
}
public static void main(String args []){
S s1 = new S("a");
S s2 = new S("b");
S s3 = new S("a");
Map m = new HashMap ();
m.put(s1, "v11");
m.put(s2, "v22");
m.put(s3, "v33");
System.out.println(m.size());
}
//just a plain implementation
public boolean equals(Object o)
{
S cc = (S) o;
if (this.i.equals(cc.i))
{
return true;
}
else
{
return false;
}
}
public int hashCode()
{
return 222;
}
}
在上面运行时,这将返回2的大小。它完全没问题。如果我们注释hashCode()它返回3也是正确的。但是如果我们评论等于并保持hashCode它应该返回2对吗?而将它返回3.当将对象放到hashmap map时会检查一个对象的哈希码,如果它相同,它会将地图的先前值替换为新的一个吗?
谢谢。
答案 0 :(得分:2)
但是如果我们评论等于并保持hashCode它应该返回2 对?相反,它返回3.
3项是正确的行为。 3个对象将被散列到同一个存储桶,但由于所有3个存在不同,因此该存储桶将包含一组值(Java中的HashMap的链表),具有相同的哈希码但不相等。
将对象放入hashmap map时,将检查对象的哈希码以及是否相同 它会将地图的先前值替换为新的权利吗?
如果将它们散列到同一个桶中,并不意味着一个值将替换另一个值。然后将比较这些值的相等性。如果它们相等,那么旧的值将被替换,如果它们不是 - 新的值将被添加到链表的尾部(对于这个桶)。
答案 1 :(得分:1)
哈希码仅用于确定放置对象的存储区。每个桶可以包含多个对象。因此必须实现哈希码以确保相同的对象进入同一个桶。换句话说,相等的对象必须具有相同的哈希码,但具有相同哈希码的对象不一定相等。
答案 2 :(得分:1)
当您仅覆盖hashcode
时,没有任何真正的变化。您只是将每个对象放在return 222
的同一个存储桶中。所以HashMap
效率更低,但合同不会改变。
答案 3 :(得分:0)
哈希码是第一个快速查找两个对象是否相等的方法。散列容器使用它来决定对象可以进入哪个“槽”,并在不检查所有槽中的所有对象的情况下检索它。
如果您的哈希码始终相同,则所有对象都将定向到同一个槽。这称为碰撞。插入速度会变慢,因为在碰撞之后,容器必须检查该插槽中已有的对象是否与新的对象匹配(equals
)。此外,检索将更慢,因为它必须按顺序检查它们,直到找到正确的(equals
againg)。最后,可能会有大量未使用的内存浪费在不会使用的插槽中。
实质上,通过不实现合理的哈希码,您将转换列表中的哈希容器(以及效率低下的哈希容器)。
答案 4 :(得分:0)
如果我们评论hashCode(),它返回3也是正确的。
这不对!只有2个不同的对象:“a”和“b”。 equals方法表示什么是平等的,什么不是。预期大小为2.但是,由于equals-hashcode合约被破坏,返回的大小为3。