【问题标题】:Why hashcode does not generate unique hashcode?为什么哈希码不会生成唯一的哈希码?
【发布时间】:2014-12-31 15:14:32
【问题描述】:

我们知道 hashCode() 的默认实现在将对象的内部地址converting the internal address 转换为整数后返回整数。所以每个对象的内存都不一样,那么为什么hashCode()不会生成唯一的hashcode。

我的问题是,如果我们不覆盖 hashcode() 和 equals,为什么 hashcode() [它返回一个对象的地址表示的整数] 不会生成唯一代码?

【问题讨论】:

  • 默认的equals() 也并不真正检查完全相等。要使用任何一个,您都需要覆盖它;如果您不指定方法,您希望 java 做什么?
  • 感谢您的重播但是我的问题是,如果我们不覆盖哈希码和等于,为什么哈希码不会生成唯一代码,因为它是对象的内存表示?

标签: java hashcode


【解决方案1】:

因为它不能。

由于只有 2^32 个不同的 int,并且任何 VM 实例中可能有超过 2^32 个活动对象,因此在技术上不可能保证每个对象都有唯一的哈希码。

即使默认哈希码可能基于对象的内部地址,它也不等同于内部地址。

【讨论】:

  • “因为它不能。”这不完全正确。它可以对枚举这样做。只是方法本身的契约并不要求它这样做。
  • @fge:为什么你认为枚举是可能的?
  • @jarnbjo 纯粹出于实际原因; Java 文件的来源是有限的(我无法提醒确切的限制,但肯定小于 2^32 - 1)
  • @fge:我写道,您可以使用不同的类加载器多次加载枚举类型。每个类加载器都会为您提供每个枚举值的不同实例。
  • @fge:您显然错误地假设枚举值是单例,但事实并非如此。如果您使用不同的类加载器加载枚举类型,则每个值都将是它自己的实例。但是我不知道我要重复多少次“不同的类加载器”直到你明白?
【解决方案2】:

为什么 hashCode() 不会生成唯一的哈希码

因为它没有义务这样做……

引用Object.hashCode()的javadoc:

要求如果两个对象根据 equals(java.lang.Object) 方法不相等,则对两个对象中的每一个调用 hashCode 方法必须产生不同的整数结果。

事实上,这是一个完全合法(尽管没用)的 hashCode 实现:

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

.hashCode() 方法要求的是如果两个对象根据.equals() 相等,那么它们对于.hashCode() 应该有相同的结果;上面的方法符合要求!

请注意,在现实生活中,你永远不会编写像上面这样无用的 hashCode() 方法......


注意默认实现,即Object

  • 它的hashCode()方法调用System.identityHashCode()
  • 它的equals() 方法测试引用相等性(即,对于对象o1o2,它测试o1 == o2)。

如果你仔细阅读Object 的javadoc,你会发现这两种方法的约定都被遵守了;它的实现尽可能少,但遵守合同。

【讨论】:

  • 您应该将文档中的这一重要引述纳入您的答案中。 “这通常通过将对象的内部地址转换为整数来实现,但Java™ 编程语言不需要这种实现技术。”
  • @fge 感谢您的重播
  • @neelabhsingh 请注意,您只能接受一个答案;请务必接受最能回答您问题的那个!
  • @Radiodef 不确定这是否是这里真正重要的部分...... OP 似乎被误导到什么真正绑定 hashCode() 开始;更不用说不能保证“相同”对象的哈希码在不同的 JVM 运行中是相同的
【解决方案3】:

hashCode 仅在没有被覆盖的情况下打印内部存储器地址! (它使用对象实现)

String 对象的哈希码计算为

 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

使用int算术,其中s[i]是字符串的第i个字符,n是字符串的长度,^表示求幂。 (空字符串的哈希值为零。)

【讨论】:

  • 感谢您的重播
  • *reply :) 重播是不同的。不要对此评论感到冒犯
【解决方案4】:

一个对象的哈希码不是它的内存地址。如果您需要为实例使用唯一整数,则有一个特殊的方法,称为System.identityHashCode(Object)

哈希码只是一个整数(32 位),旨在给出一个合理的相等近似值。如果两个哈希码不同,则这两个对象一定不同,但如果它们相同,它们可能仍然不同(尽管通常它们是相同的)。

这意味着,如果您有两个内容完全相同的不同列表,它们将具有相同的哈希码,但内存地址不同。

【讨论】:

  • identityHashCode 不是地址,也不必基于地址。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-01
  • 2014-05-11
  • 1970-01-01
  • 2011-02-15
  • 2013-04-11
相关资源
最近更新 更多