如何使用String.hashCode生成主键

时间:2014-03-11 10:47:37

标签: java string primary-key hashcode

我知道这似乎已经讨论过,答案是肯定的,String.hashCode可以为不同的字符串生成相同的值,但不太可能(Can Java's hashCode produce same value for different strings?)。但是它确实发生在我的应用程序中。

以下代码将生成相同的哈希码:-347019262(jave 1.7.25)

String string1 = "/m/06qw_";
String string2="/m/0859_";
System.out.println(string1+","+string1.hashCode());
System.out.println(string2+","+string2.hashCode());

在这种情况下我确实需要哈希码,我想用它来为字符串生成唯一的主键。看来我做得不对。有什么建议吗?

非常感谢!

5 个答案:

答案 0 :(得分:13)

你误解了.hashCode()

合同的一部分是equals()的对象必须具有相同的hashCode()。但是,情况恰恰相反:具有相同hashCode() 的两个对象必须为equals()

这是一个有效的,虽然完全无用的hashCode()实施:

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

您应该将字符串本身用作“主键”。如果你想要一个“更有效”的键,你应该考虑输入字符串是什么格式,如果可能的话,提取这个输入的重要部分。

答案 1 :(得分:4)

明智的选择是使用字符串作为主键。 (另一种选择是将GUID与您的数据记录相关联,并将其作为主键。)

哈希意味着(1)快速和(2)使得两个相等的字符串具有相同的哈希码。

我提交可能得到哈希冲突;毕竟int(散列返回类型)只有大约40亿个不同的值。

答案 2 :(得分:2)

您可以使用SHA1哈希算法来降低冲突概率。看看这个片段,看看如何在Java中计算SHA1哈希:http://www.sha1-online.com/sha1-java/

答案 3 :(得分:2)

您可以使用

System.identityHashcode(Object);

获得独特的结果。

修改

我认为这可能是杂音哈希番石榴的实施也可以在这里帮助:

 HashFunction hash = Hashing.murmur3_128();
 hash.hashString("/m/06qw_", Charset.defaultCharset()).asInt();

一般来说,murmur hash应该是快速可靠的。

答案 4 :(得分:2)

  

在这种情况下我确实需要哈希码,我想用它来为字符串生成唯一的主键。看来我做得不对。有什么建议吗?

您应该始终谨慎使用哈希值主键。它们并不是唯一的。哈希函数的范围越小,问题就越严重。

在您的情况下,hashcode(以及评论中建议的identityHashcode()方法)会生成32位值。对于任意一对两个不同的随机生成的字符串,在2 ^ 32中有一个机会,即哈希码将是相同的。对于生成(32位)哈希码的任何方法都是如此。

现在(大约)20亿分之一的机会听起来并不多。但是,你不需要只有成对的独特性。你实际上需要所有你的字符串'哈希码是唯一的...因为您尝试使用哈希码作为主键,主键必须是唯一的。维基百科页面上的表格" birthday problem"说在碰撞的可能性上升到1/4之前你只需要大约50,000把钥匙。(是的......四分之一!)

简而言之,请勿使用hashcode()值作为主键。

同一个表,表示生成128位散列值的良好散列函数可能足以避免冲突。但要检查自己的可能性并做出自己的判断。