【问题标题】:Are two Java objects with same hashcodes not necessarily equal?具有相同哈希码的两个 Java 对象不一定相等吗?
【发布时间】:2011-07-23 12:33:21
【问题描述】:

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

【问题讨论】:

标签: java hashcode


【解决方案1】:

如果两个对象具有相同的hashcode,那么它们不一定相等。否则你会发现完美的散列函数。

但反之亦然:如果对象相等,则它们必须具有相同的hashcode

【讨论】:

  • +1 这通常也与散列对象有关,而不仅仅是 java 对象。
  • 考虑这个example 这里firstBooksecondBook 有不同的哈希码。那么你的陈述如何是真的if the objects are equal then they have the same hashcode
  • @Fresher - 抱歉回复晚了。当两个对象相等时,您必须覆盖哈希码,以便哈希码也相等。否则在集合中使用对象时会出现问题。在您给定的示例中,他们编写了If you override equals(), you must override hashCode() as well. 您只看到声明的equals 方法,因为他们只在段落中谈论equals。注意上面有...。这意味着hashcode 方法不是故意编写的,因此它们仅显示equals 方法。但是必须添加hashcode方法。
  • 所以你说you must override hashcode so that the hashcodes are equal too.这意味着你说firstBook and secondBook具有相等的哈希码或者你说我们必须重写哈希码方法,以便我们使它们的哈希码相等。
  • @Fresher - 我是说你必须重写 hashcode 方法,所以当 equals 返回 true 时,hashcode 是相等的。这意味着您必须在 hashcode 中使用与 equals 比较中相同的字段。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    证明,如果两个对象有相同的 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   
        }
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

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

            在合理可行的情况下,hashCode 方法定义为 类 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
            

            【讨论】:

              【解决方案8】:

              事实上

              public int hashCode(){
                  return 1;
              }
              

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

              【讨论】:

              • 这是一个有效的参数。为了确保正确性,哈希码必须满足的唯一属性是,如果底层数据结构不同,则哈希码应该不同。这是因为不同的哈希码在设计上意味着不同的底层结构。
              • “不同的底层结构”是什么意思?
              【解决方案9】:

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

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

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

              【讨论】:

                猜你喜欢
                • 2013-04-30
                • 1970-01-01
                • 2012-09-24
                • 1970-01-01
                • 2011-10-21
                • 1970-01-01
                • 1970-01-01
                • 2011-09-23
                相关资源
                最近更新 更多