2016-04-25 67 views
1

我想为字符串生成一个整数哈希码,它将永远保持不变;即相同的字符串应始终导致相同的哈希码。字符串的持久哈希码

散列不必是加密安全的,它不会用于密码或敏感数据。

我的第一次尝试是使用.net框架string.GetHashCode()函数。 但是在阅读的来源,我发现以下commment:

// We want to ensure we can change our hash function daily. 
// This is perfectly fine as long as you don't persist the 
// value from GetHashCode to disk or count on String A 
// hashing before string B. Those are bugs in your code. 
hash1 ^= ThisAssembly.DailyBuildNumber; 

这似乎表明,哈希码不会保持不变。

如果是这样,框架是否有另一种方法来生成可重复的hashcode?或者,来自GetHashCode的代码是实现我自己的合理起点吗?

我正在寻找尽可能轻巧和快速的东西。
我发现System.Security.Cryptography.MD5,但这似乎矫枉过正一个简单的int32哈希码,我担心的开销。至少需要将字符串转换为字节数组,并将字节数组转换为int,并为每个散列创建一个新的MD5()对象,或者管理某个静态共享MD5对象()。

+1

如果你对Google的“字符串散列码算法”,你会得到很好的结果。没有必要有人复制代码并将其发布到此处。 – usr

+0

我不需要一个未知质量的代码示例来生成哈希码,我正在寻找.net框架方法或方法组合,因为这似乎是任何框架的基本需求。我非常惊讶的是,string.GetHashCode显然没有用于此目的,我无法找到合适的替代方案。我还希望一个答案能够帮助其他人和我一样,它显示了这个功能在框架中隐藏的位置,或者说它不存在。 – HugoRune

+0

终于给我一个好结果的搜索字词是“.net稳定字符串哈希码”。 – usr

回答

9

没有内置的交叉版本稳定的方法来获取字符串的哈希码。

您可以复制现有的GetHashCode()代码,但排除将内部版本号作为种子添加的部分,并且不要使用不安全的调用来确保您的安全性免受实施细节更改的影响。

这是64bit GetHashCode()的完全管理版本,它不使用任何随机化,并且将为所有未来版本的.NET返回相同的值(只要int^char的行为从不改变)。

public static class StringExtensionMethods 
{ 
    public static int GetStableHashCode(this string str) 
    { 
     unchecked 
     { 
      int hash1 = 5381; 
      int hash2 = hash1; 

      for(int i = 0; i < str.Length && str[i] != '\0'; i += 2) 
      { 
       hash1 = ((hash1 << 5) + hash1)^str[i]; 
       if (i == str.Length - 1 || str[i+1] == '\0') 
        break; 
       hash2 = ((hash2 << 5) + hash2)^str[i+1]; 
      } 

      return hash1 + (hash2*1566083941); 
     } 
    } 
} 
+0

顺便说一句,这是接近当前(4.5/4.6)实际GetHashCode String.cs中。 –

+0

@JonathanNappee我说过了,我甚至在答案中链接到了String.cs。然而,“真正的”一个使用指针,并依赖于字符串映射到char *的实现细节。做指针会稍微快一点,但它不是未来的证明,因为改变字符串如何存储在内存中会改变哈希码。 –

+0

我的不好,没有看到链接指向的地方。 –