两个具有相同哈希码的Java对象不一定相等吗?

时间:2011-03-26 15:02:50

标签: java hashcode

我理解为什么为两个相等(通过equals)对象提供相同的哈希码很重要。但反过来也是如此,如果两个对象具有相同的哈希码,它们必须相等吗?合同是否仍然有效?我无法找到可能发生这种情况的示例,因为如果所有参与equals方法的属性也被用于覆盖hashcode方法,那么我们将始终使用相同的对象的哈希码。请评论。

9 个答案:

答案 0 :(得分:44)

如果两个对象具有相同的哈希码,则它们不一定相等。否则你会发现完美的哈希函数。但事实恰恰相反 - 如果对象相等,那么它们必须具有相同的哈希码。

答案 1 :(得分:7)

hashCode函数的目的是允许对象快速分割成已知不等于其自身集合之外的所有项目的集合。假设一个有1,000个项目,一个将它们分成十个大致相等大小的集合。对hashCode的一次调用可以快速将项目标识为不等于900项,而无需在任何这些项目上使用equals。即使必须使用equals将项目与其他100个项目进行比较,这仍然只是将其与所有1000个项目进行比较的成本的1/10。在实践中,即使在大型集合中,hashCode通常也会消除99.9%或更多的不平等项目,最多只能进行一些检查。

答案 2 :(得分:5)

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

  

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

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

答案 3 :(得分:3)

事实上

public int hashCode(){
    return 1;
}

是一个有效的哈希码实现......但是很糟糕。会使你的所有哈希表变慢。 但是,是的,您可以使用相同的哈希码来拥有两个不同的对象。但这不应该是一般情况,真正的实现应该在大多数情况下为不同的值提供不同的哈希码。

答案 4 :(得分:2)

奇怪的是,NumberFormat是Java基础类的一个例子,它违反了以下建议:

  

尽可能合理实用,由hashCode方法定义   class Object确实为不同的对象返回不同的整数。

以下是一些显示此问题的代码,至少在我目前在Mac OS X 10.6下运行的Java版本下。

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

答案 5 :(得分:1)

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

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

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

答案 6 :(得分:0)

散列码方法返回整数。如果整数范围结束,那么两个不同的对象将具有相同的哈希码。因此,两个不同的对象不必具有相同的哈希码是相等的。

答案 7 :(得分: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   
    }

答案 8 :(得分:0)

hashcode()为每个对象返回唯一的整数ID。如果一个对象的哈希码与另一个对象的哈希码不同,则没有理由执行equals()方法:您只知道两个对象是不同的。另一方面,如果哈希码相同,则必须执行equals()方法来确定值和字段是否相同。