2011-03-26 71 views
9

我明白为什么为两个相同的对象(通过equals)提供相同的散列码很重要。但反之亦然,如果两个对象具有相同的哈希码,它们必须相等吗?合同是否仍然成立?我找不到可能发生这种情况的示例,因为如果所有参与equals方法的属性都被用于重写hashcode方法,那么我们始终会使用相同的对象的相同hashcode。请给出意见。具有相同哈希码的两个Java对象不一定相等吗?

+1

见http://stackoverflow.com/questions/ 4360035/why-hashcode-can-return-the-same-value-for-different-objects-in-java – esaj 2011-03-26 15:05:42

回答

27

如果两个对象具有相同的哈希码,则它们不一定相等。否则,你会发现完美的散列函数。但情况正好相反 - 如果对象相同,则它们必须具有相同的哈希码。

+5

+1这与散列对象一般也不相关,不仅仅是java对象。 – MByD 2011-03-26 15:08:19

+0

考虑这个[示例](http://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html)在这里'firstBook'和'secondBook'有不同的hashcode。所以你的陈述是真实的'如果对象相同,那么他们有相同的哈希码' – Fresher 2014-05-21 13:10:03

+1

多么愚蠢的答案......他似乎没有回答为什么? – anshulkatta 2014-06-02 19:42:20

4

根据在Javadoc:http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode%28%29

不需要它,如果两个对象根据equals不相等(java.lang.Object)方法,则调用每个两者的hashCode方法对象必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

编辑:在现实世界中,两个字符串可能具有相同的哈希码。例如,如果要存储长度为10的所有包含小写英文字母的字符串组合(如“aaaaaaaaaa”,“aaaaaaaaab”等),则不能为每个141.167.095.653分配一个唯一的哈希码。 376个组合,因为Java中的int是32位,因此最多可以有4.294.967.296个不同的值。

2

事实上

public int hashCode(){ 
    return 1; 
} 

的问题是一个有效的哈希码实现......但可怕之一。将使所有的哈希表缓慢。 但是,您可以拥有两个具有相同哈希码的不同对象。但是这不应该是一般情况,真正的实现应该在大多数情况下为不同的值提供不同的哈希码。

+0

这是一个有效的论点。哈希代码必须满足以确保正确性的唯一属性是哈希代码应该不同*只有*如果底层数据结构不同。这是因为不同的哈希码在设计上意味着不同的基础结构。 – Jasim 2012-09-25 07:37:59

+0

你是什么意思的“不同的基础结构”? – NoName 2017-06-24 06:27:27

2

奇怪的是,NumberFormat的是这违反,该建议一个Java基础类的一个示例:

多达是合理可行,通过 类对象定义的hashCode方法并返回不同的整数为不同的对象。

下面是一些代码,至少在Java的版本下我目前在Mac OS X 10.6下运行。

Numberformat nf = NumberFormat.getNumberInstance(); 
NumberFormat nf2 = NumberFormat.getNumberInstance(); 
assert nf != nf2; // passes -- they are different objects 
assert !nf.equals(nf2); // passes -- they are not equal 
assert nf.hashCode() != nf2.hashCode(); // fails -- same hash code 
1

hashCode值取决于实施。例如String类根据值实现hashCode()函数。这意味着

String a=new String("b"); 
String b=new String("b"); 

将有相同hashcode但是,这是两个不同的对象。 a==b将返回false

4

hashCode函数的作用是允许对象快速分割成已知不同于其自身集外的所有项目的集合。假设一个人拥有1,000个项目,并将其分成十个大致相等大小的集合。拨打hashCode的一个电话可以快速识别该物品不等于900个物品,而不必在这些物品上使用equals。即使必须使用equals将该项目与其他100个项目进行比较,这仍然只是将其与所有1000个项目进行比较的成本的1/10。实际上,即使在大量收集中,hashCode通常也会消除99.9%或更多的不相等项目,最多只有少数人被检查。

0

哈希码方法返回整数。如果整数范围结束,那么两个不同的对象也将具有相同的散列码。所以不需要两个不同的对象具有相同的哈希码。

0

为了证明,如果两个对象具有相同的 的hashCode并不意味着他们是平等的

说你有两个用户定义的类

class Object1{ 
     private final int hashCode = 21; 
     public int hashCode(){ 
      return hashCode; 
     } 

     public boolean equals(Object obj) { 
      return (this == obj); 
     } 
    } 

    class Object2{ 
     private final int hashCode = 21; 
     public int hashCode(){ 
      return hashCode; 
     } 

     public boolean equals(Object obj) { 
      return (this == obj); 
     } 
    } 

    Object1 object1 = new Object1(); 
    Object2 object2 = new Object2(); 

    Object1 object3 = new Object1(); 


    if(object1.hashCode() == object2.hashCode()){ 
     // return true, because the hashcodes are same 
    } 

    but 
    if(object1.equals(object3)){ 
      // will fail, because two different objects 
    } 
相关问题