2011-08-31 77 views
0

假设我有下面的类。以哈希值为基础的对象抽取集合

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,这也是正确的。但是如果我们评论equals并保留hashCode,它应该返回2对吗?相反,它返回3.当把对象放到hashmap map中时,会检查一个对象的哈希码,如果它相同,它会将之前的地图值替换为新的哈希值。

谢谢。

回答

2

但是,如果我们评论等于并保留hashCode它应该返回2 对不对?相反它返回3.

3项是正确的行为。 3个对象将被散列到同一个桶中,但是因为所有3个都不相同,所以这个桶将包含具有相同散列代码但不相等的值链(Java中的HashMap的链接列表)。

当把对象HashMap的地图将检查对象的哈希码,如果它同 将地图的前值替换到右边新建一个?

如果将它们散列到同一个存储桶中,这并不意味着一个值将取代另一个值。然后将这些值进行比较以得到平等。如果它们相等,则旧值将被替换,如果它们不是 - 将新值添加到链表的尾部(对于该桶)。

1

散列码仅用于确定放置对象的存储区。每个桶可以包含多个对象。所以必须实现哈希码以确保相同的对象进入同一个桶。换句话说,相同的对象必须具有相同的哈希码,但具有相同哈希码的对象不一定相等。

1

当你只覆盖hashcode没有什么真正改变。您只需将每个对象与return 222放在同一个存储桶中即可。所以HashMap效率更低,但其合同不会改变。

0

哈希码是第一个快速找到两个对象是否相等的方法。散列容器使用它来决定对象可能在哪个“插槽”中进行检索,并检索它而不检查所有插槽中的所有对象。

如果你的散列码总是相同的,那么所有的对象将被定向到相同的插槽。这叫做碰撞。插入将会更慢,因为在碰撞后容器将不得不检查已经在该插槽中的物体是否与新的物体相匹配(equals)。另外,检索速度会比较慢,因为它必须依次检查它们,直到找到正确的(equals againg)。最后,可能会有很多未使用的内存被浪费在不被使用的插槽中。

实质上,通过不实现明智的散列码,您将转换列表中的散列容器(以及低效的散列容器)。

0

如果我们评论hashCode()它返回3,这也是正确的。

这是不正确的!只有2个不同的对象:“a”和“b”。平等的方法说什么是平等的,什么不是。预期的大小是2.但是,因为equals-hashcode合同被破坏,返回的大小为3.