【问题标题】:is the int value of String.hashCode() unique?String.hashCode() 的 int 值是否唯一?
【发布时间】:2014-09-09 03:59:51
【问题描述】:

几天前我遇到了一个问题。现在我有数千万字,字符串类型。现在我决定将它们保存在数据库中并使用索引来保持它们的唯一性。我不想比较原始单词来保持它们的唯一性。我想确定一个字符串的 hashCode() 方法是否可以是唯一的,如果使用另一台笔记本电脑或不同的时间或类似的东西,它不会改变吗?

【问题讨论】:

  • 不,它是确定性的。
  • hashCode 可以返回多少个 distinct 值?有多少个 distinct 字符串? GO!!! FIT IN!
  • 无论如何,tldr;这适合使用 hashCode。虽然像 SHA-x 这样的哈希没有这些“问题”(或者我们可以假装不太可能关心冲突),但如果只比较单个单词,那么生成的哈希(SHA-1 为 20 个字节)大于原始输入!没有胜利!
  • 假设 RDBMS,将​​ AUTO-INCREMENT 字段添加到您的表中,它将在 INSERT 期间填充唯一数字。
  • @user2864740 字符串的 hashCode 由 String API specification 定义,因此对于跨实现的相等字符串,它必须相同。

标签: java string unique hashcode


【解决方案1】:

独一无二,不。从本质上讲,哈希值不能保证是唯一的。

任何具有任意数量的可能输入和有限数量的输出的系统都会发生冲突。

因此,如果 only 基于哈希码,您将无法使用 唯一 数据库密钥来存储它们。但是,您可以使用非唯一密钥来存储它们。

回答你的第二个问题,不同版本的Java是否会为同一个字符串生成不同的哈希码,不会。

如果 Java 实现遵循 Oracle 文档(否则它不是真正的 Java 实现),它将在所有实现中保持一致。 Oracle docs for String.hashCode指定了一个固定的计算hash的公式:

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

如果您使用完全不同的 Java 版本(例如 1.2 与 8),您可能需要检查是否仍然如此,但这种情况已经存在很长时间了,至少从1.5.

【讨论】:

  • 事实上,根据鸽巢原理,由于有(远)多于 2^32 个可能的字符串,哈希码保证不唯一。
【解决方案2】:

不,

因为 java 中的字符串最多可以有 2,147,483,647 (2^31 - 1) 个字符,并且所有字符都会变化,所以它会产生非常大的组合数,但整数的范围只有 -2,147,483,648 到 2,147,483,648。所以这是不可能的,使用这种方法计算一个字符串的哈希码

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

例子:

如果您创建两个字符串变量为“FB”和“Ea”,则哈希码将相同。

【讨论】:

    【解决方案3】:

    下面是 JVM 对 String 的 hashCode 计算。如前所述,它纯粹基于单个字符及其在字符串中的位置进行计算,并且没有任何依赖于 JVM 或运行 JVM 的机器类型会改变哈希码。

    这也是为什么 String 类被声明为 final (不可扩展导致不变性)以便没有人改变其行为的原因之一。

    以下是按照规范:-

    public int hashCode()
    

    返回此字符串的哈希码。 String 对象的哈希码计算为

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-03
      • 2010-09-13
      • 2023-03-18
      • 2016-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多