繁体   English   中英

在JVM堆中,可以有多个具有相同哈希码的对象吗?

[英]In JVM heap can there be more than one object with the same hash code?

按照标题,堆上是否可以有多个具有相同哈希码的对象?

是。

public class MyObject {
    @Override
    public int hashCode() {
        return 42;
    }

    public static void main(String[] args) {
        MyObject obj1 = new MyObject();
        MyObject obj2 = new MyObject(); // Ta-da!
    }
}

对于一个不那么轻松的答案,请考虑hashCode Javadocs

hashCode的一般约定为:

  • ...(剪断)...
  • 如果根据equals(Object)方法,两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。

是的 ,因为您可以根据需要拥有多个具有相同hashCode对象。 例如,下面的代码, 没有内部String ,就说明了这一事实:

String foo = new String("dfa");
String bar = new String("dfa");
assert foo != bar; // yields false, two distinct objects (references)
assert foo.hashCode() == bar.hashCode(); // yields true

简单证明:hashCode返回一个32位整数。

分配2 ^ 32 + 1个对象。 (为此可能需要64位VM和大量RAM!;-))

现在,无论多么聪明,您的hashCode方法都必须发生冲突。

关于哈希码:是的,它们几乎相同,但并不是唯一的。 :)取决于实现/理论,它们有多独特。

但是,如果我们谈论JVM,则必须首先谈论您的意思是哪种哈希码。

如果您谈论HashMap使用的hashCode()方法的结果,那么答案是:它取决于您的实现和JVM中对象的数量。
解决此冲突是您的选择,计划和知识,您可以使用自行实现的hashCode()方法来解决此冲突。

如果您谈论方法System.identityHashCode(obj)的结果,则它会有所不同。 此实现不会调用您的hashCode()方法。 而且实现不是唯一的-但它几乎是唯一的,就像许多其他不同的哈希函数一样。 :)

public class MyObject {
    @Override
    public int hashCode() {
        return 42;
    }

    public static void main(String[] args) {
        MyObject obj1 = new MyObject();
        MyObject obj2 = new MyObject(); // Ta-da!

        final int obj1Hash = System.identityHashCode( obj1 );
        final int obj2Hash = System.identityHashCode( obj2 );

        if( obj1Hash == obj2Hash ) throw new IllegalStateException();
    }
}

在此示例中,您将获得不同的哈希值,并且在大多数情况下它们是不同的,但不一定是唯一的...

最好的祝福!

是的,哈希码是一种标准算法,试图避免重复(“冲突”),但不能保证一定会重复。

而且,它是可重写的,因此您可以编写自己的实现,为每个对象产生相同的哈希码; 至于为什么要这么做,我没有答案。 :-)

您可以,但这通常不是一个好主意。 上面多次提到该示例:

public int hashCode(){
     return 1;
}

在hashCode()的规范下完全有效。 但是,这样做会使HashMap变成一个链表,这会大大降低性能。 因此,您通常希望实现hashCode来返回尽可能唯一的值。

但是,实际上,许多实现可能会发生冲突。 以这个为例:

public class OrderedPair{
     private int x;
     private int y;

     public int hashCode(){
          int prime = 31;
          int result=x;
          result =result*prime+y;
          return result; 
     }

     public boolean equals(){...}
}

这是hashCode()一个非常标准的实现(实际上,它非常接近在IDEA和Eclipse中自动生成的输出),但是它可能会发生很多冲突:x = 1,y = 0和x = 0, y = 1将适合初学者。 编写良好的hashCode()实现的想法是避免发生足够多的冲突,以免对性能造成不适当的影响。

当然,显然您可以编写:

class MyClass{
   ...
   public int hashCode(){
      return 1;
   }
   ...
}

在这种情况下,MyClass的所有实例将具有相同的哈希码。

是的,您当然可以有多个具有相同哈希码的对象。 但是,通常这不会引起问题,因为使用对象哈希码的java.util。*数据结构将其用作存储所有返回相同哈希值的对象的“存储桶”的键。

Object a = new Integer(1);
Object b = new Integer(1);

System.out.printf(" Is the same object?     = %s\n",(a == b ));
System.out.printf(" Have the same hashCode? = %s\n",( a.hashCode() == b.hashCode() ));

印刷品:

Is the same object?     = false
Have the same hashCode? = true

在32位环境中,我怀疑任何JVM都会为不同的对象返回相同的“身份哈希码”。 但是在64位中,这肯定是可能的; 考虑到我们现在的内存有限,发生碰撞的可能性仍然很小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM