本文系转载,转自:http://www.blogjava.net/jinfei0627/articles/219543.html

应用Hash函数(java描述)

作者:冲处宇宙

时间:2007.1.25

计算理论中,没有Hash函数的说法,只有单向函数的说法。所谓的单向函数,是一个复杂的定义,大家可以去看计算理论或者密码学方面的数据。用“人类”的语言描述单向函数就是:如果某个函数在给定输入的时候,很容易计算出其结果来;而当给定结果的时候,很难计算出输入来,这就是单项函数。各种加密函数都可以被认为是单向函数的逼近。Hash函数(或者成为散列函数)也可以看成是单向函数的一个逼近。即它接近于满足单向函数的定义。

Hash函数还有另外的含义。实际中的Hash函数是指把一个大范围映射到一个小范围。把大范围映射到一个小范围的目的往往是为了节省空间,使得数据容易保存。除此以外,Hash函数往往应用于查找上。所以,在考虑使用Hash函数之前,需要明白它的几个限制:

1. Hash的主要原理就是把大范围映射到小范围;所以,你输入的实际值的个数必须和小范围相当或者比它更小。不然冲突就会很多。

2. 由于Hash逼近单向函数;所以,你可以用它来对数据进行加密。

3. 不同的应用对Hash函数有着不同的要求;比如,用于加密的Hash函数主要考虑它和单项函数的差距,而用于查找的Hash函数主要考虑它映射到小范围的冲突率。

应用于加密的Hash函数已经探讨过太多了,在作者的博客里面有更详细的介绍。所以,本文只探讨用于查找的Hash函数。

Hash函数应用的主要对象是数组(比如,字符串),而其目标一般是一个int类型。以下我们都按照这种方式来说明。

一般的说,Hash函数可以简单的划分为如下几类:

1. 加法Hash;

2. 位运算Hash;

3. 乘法Hash;

4. 除法Hash;

5. 查表Hash;

6. 混合Hash;

下面详细的介绍以上各种方式在实际中的运用。

一 加法Hash

所谓的加法Hash就是把输入元素一个一个的加起来构成最后的结果。标准的加法Hash的构造如下:

[java] view
plain
copy

  1. static int additiveHash(String key, int prime)
  2. {
  3. int hash, i;
  4. for (hash = key.length(), i = 0; i < key.length(); i++)
  5. hash += key.charAt(i);
  6. return (hash % prime);
  7. }

这里的prime是任意的质数,看得出,结果的值域为[0,prime-1]。

二 位运算Hash

这类型Hash函数通过利用各种位运算(常见的是移位和异或)来充分的混合输入元素。比如,标准的旋转Hash的构造如下:

[java] view
plain
copy

  1. static int rotatingHash(String key, int prime)
  2. {
  3. int hash, i;
  4. for (hash=key.length(), i=0; i<key.length(); ++i)
  5. hash = (hash<<4)^(hash>>28)^key.charAt(i);
  6. return (hash % prime);
  7. }

先移位,然后再进行各种位运算是这种类型Hash函数的主要特点。比如,以上的那段计算hash的代码还可以有如下几种变形:

[java] view
plain
copy

  1. 1.     hash = (hash<<5)^(hash>>27)^key.charAt(i);
  2. 2.     hash += key.charAt(i);
  3. hash += (hash << 10);
  4. hash ^= (hash >> 6);
  5. 3.     if((i&1) == 0)
  6. {
  7. hash ^= (hash<<7) ^ key.charAt(i) ^ (hash>>3);
  8. }
  9. else
  10. {
  11. hash ^= ~((hash<<11) ^ key.charAt(i) ^ (hash >>5));
  12. }
  13. 4.     hash += (hash<<5) + key.charAt(i);
  14. 5.     hash = key.charAt(i) + (hash<<6) + (hash>>16) – hash;
  15. 6.     hash ^= ((hash<<5) + key.charAt(i) + (hash>>2));

三 乘法Hash

这种类型的Hash函数利用了乘法的不相关性(乘法的这种性质,最有名的莫过于平方取头尾的随机数生成算法,虽然这种算法效果并不好)。比如,

[java] view
plain
copy

  1. static int bernstein(String key)
  2. {
  3. int hash = 0;
  4. int i;
  5. for (i=0; i<key.length(); ++i) hash = 33*hash + key.charAt(i);
  6. return hash;
  7. }

jdk5.0里面的String类的hashCode()方法也使用乘法Hash。不过,它使用的乘数是31。推荐的乘数还有:131, 1313, 13131, 131313等等。

使用这种方式的著名Hash函数还有:

[java] view
plain
copy

  1. //  32位FNV算法
  2. int M_SHIFT = 0;
  3. public int FNVHash(byte[] data)
  4. {
  5. int hash = (int)2166136261L;
  6. for(byte b : data)
  7. hash = (hash * 16777619) ^ b;
  8. if (M_SHIFT == 0)
  9. return hash;
  10. return (hash ^ (hash >> M_SHIFT)) & M_MASK;
  11. }

以及改进的FNV算法:

[java] view
plain
copy

  1. public static int FNVHash1(String data)
  2. {
  3. final int p = 16777619;
  4. int hash = (int)2166136261L;
  5. for(int i=0;i<data.length();i++)
  6. hash = (hash ^ data.charAt(i)) * p;
  7. hash += hash << 13;
  8. hash ^= hash >> 7;
  9. hash += hash << 3;
  10. hash ^= hash >> 17;
  11. hash += hash << 5;
  12. return hash;
  13. }

除了乘以一个固定的数,常见的还有乘以一个不断改变的数,比如:

[java] view
plain
copy

  1. static int RSHash(String str)
  2. {
  3. int b    = 378551;
  4. int a    = 63689;
  5. int hash = 0;
  6. for(int i = 0; i < str.length(); i++)
  7. {
  8. hash = hash * a + str.charAt(i);
  9. a    = a * b;
  10. }
  11. return (hash & 0x7FFFFFFF);

虽然Adler32算法的应用没有CRC32广泛,不过,它可能是乘法Hash里面最有名的一个了。关于它的介绍,大家可以去看RFC 1950规范。

四 除法Hash

除法和乘法一样,同样具有表面上看起来的不相关性。不过,因为除法太慢,这种方式几乎找不到真正的应用。需要注意的是,我们在前面看到的hash的结果除以一个prime的目的只是为了保证结果的范围。如果你不需要它限制一个范围的话,可以使用如下的代码替代”hash%prime”: hash = hash ^ (hash>>10) ^ (hash>>20)。

五 查表Hash

查表Hash最有名的例子莫过于CRC系列算法。虽然CRC系列算法本身并不是查表,但是,查表是它的一种最快的实现方式。下面是CRC32的实现:

[java] view
plain
copy

  1. static int crctab[256] = {
  2. 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,  0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,  0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,  0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,  0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,  0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,  0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,  0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,  0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,  0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,  0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,  0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,  0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
  3. 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,  0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,  0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,  0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,  0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,  0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,  0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,  0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,  0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
  4. };
  5. int crc32(String key, int hash)
  6. {
  7. int i;
  8. for (hash=key.length(), i=0; i<key.length(); ++i)
  9. hash = (hash >> 8) ^ crctab[(hash & 0xff) ^ k.charAt(i)];
  10. return hash;
  11. }

查表Hash中有名的例子有:Universal Hashing和Zobrist Hashing。他们的表格都是随机生成的。

六 混合Hash

混合Hash算法利用了以上各种方式。各种常见的Hash算法,比如MD5、Tiger都属于这个范围。它们一般很少在面向查找的Hash函数里面使用。

七 对Hash算法的评价

http://www.burtleburtle.net/bob/hash/doobs.html 这个页面提供了对几种流行Hash算法的评价。我们对Hash函数的建议如下:

1. 字符串的Hash。最简单可以使用基本的乘法Hash,当乘数为33时,对于英文单词有很好的散列效果(小于6个的小写形式可以保证没有冲突)。复杂一点可以使用FNV算法(及其改进形式),它对于比较长的字符串,在速度和效果上都不错。

2. 长数组的Hash。可以使用http://burtleburtle.net/bob/c/lookup3.c这种算法,它一次运算多个字节,速度还算不错。

八 后记

本文简略的介绍了一番实际应用中的用于查找的Hash算法。Hash算法除了应用于这个方面以外,另外一个著名的应用是巨型字符串匹配(这时的Hash算法叫做:rolling hash,因为它必须可以滚动的计算)。设计一个真正好的Hash算法并不是一件容易的事情。做为应用来说,选择一个适合的算法是最重要的。

常用hash算法类:

[java] view
plain
copy

  1. package lotusroots.algorithms.math;
  2. import java.security.MessageDigest;
  3. /**
  4. * Hash算法大全<br>
  5. * 推荐使用FNV1算法
  6. *
  7. * @algorithm None
  8. * @author Goodzzp 2006-11-20
  9. * @lastEdit Goodzzp 2006-11-20
  10. * @editDetail Create
  11. */
  12. public class HashAlgorithms {
  13. /**
  14. * 加法hash
  15. *
  16. * @param key
  17. *            字符串
  18. * @param prime
  19. *            一个质数
  20. * @return hash结果
  21. */
  22. public static int additiveHash(String key, int prime) {
  23. int hash, i;
  24. for (hash = key.length(), i = 0; i < key.length(); i++)
  25. hash += key.charAt(i);
  26. return (hash % prime);
  27. }
  28. /**
  29. * 旋转hash
  30. *
  31. * @param key
  32. *            输入字符串
  33. * @param prime
  34. *            质数
  35. * @return hash值
  36. */
  37. public static int rotatingHash(String key, int prime) {
  38. int hash, i;
  39. for (hash = key.length(), i = 0; i < key.length(); ++i)
  40. hash = (hash << 4) ^ (hash >> 28) ^ key.charAt(i);
  41. return (hash % prime);
  42. // return (hash ^ (hash>>10) ^ (hash>>20));
  43. }
  44. // 替代:
  45. // 使用:hash = (hash ^ (hash>>10) ^ (hash>>20)) & mask;
  46. // 替代:hash %= prime;
  47. /**
  48. * MASK值,随便找一个值,最好是质数
  49. */
  50. static int M_MASK = 0x8765fed1;
  51. /**
  52. * 一次一个hash
  53. *
  54. * @param key
  55. *            输入字符串
  56. * @return 输出hash值
  57. */
  58. public static int oneByOneHash(String key) {
  59. int hash, i;
  60. for (hash = 0, i = 0; i < key.length(); ++i) {
  61. hash += key.charAt(i);
  62. hash += (hash << 10);
  63. hash ^= (hash >> 6);
  64. }
  65. hash += (hash << 3);
  66. hash ^= (hash >> 11);
  67. hash += (hash << 15);
  68. // return (hash & M_MASK);
  69. return hash;
  70. }
  71. /**
  72. * Bernstein's hash
  73. *
  74. * @param key
  75. *            输入字节数组
  76. * @param level
  77. *            初始hash常量
  78. * @return 结果hash
  79. */
  80. public static int bernstein(String key) {
  81. int hash = 0;
  82. int i;
  83. for (i = 0; i < key.length(); ++i)
  84. hash = 33 * hash + key.charAt(i);
  85. return hash;
  86. }
  87. //
  88. // // Pearson's Hash
  89. // char pearson(char[]key, ub4 len, char tab[256])
  90. // {
  91. // char hash;
  92. // ub4 i;
  93. // for (hash=len, i=0; i<len; ++i)
  94. // hash=tab[hash^key[i]];
  95. // return (hash);
  96. // }
  97. // // CRC Hashing,计算crc,具体代码见其他
  98. // ub4 crc(char *key, ub4 len, ub4 mask, ub4 tab[256])
  99. // {
  100. // ub4 hash, i;
  101. // for (hash=len, i=0; i<len; ++i)
  102. // hash = (hash >> 8) ^ tab[(hash & 0xff) ^ key[i]];
  103. // return (hash & mask);
  104. // }
  105. /**
  106. * Universal Hashing
  107. */
  108. public static int universal(char[] key, int mask, int[] tab) {
  109. int hash = key.length, i, len = key.length;
  110. for (i = 0; i < (len << 3); i += 8) {
  111. char k = key[i >> 3];
  112. if ((k & 0x01) == 0)
  113. hash ^= tab[i + 0];
  114. if ((k & 0x02) == 0)
  115. hash ^= tab[i + 1];
  116. if ((k & 0x04) == 0)
  117. hash ^= tab[i + 2];
  118. if ((k & 0x08) == 0)
  119. hash ^= tab[i + 3];
  120. if ((k & 0x10) == 0)
  121. hash ^= tab[i + 4];
  122. if ((k & 0x20) == 0)
  123. hash ^= tab[i + 5];
  124. if ((k & 0x40) == 0)
  125. hash ^= tab[i + 6];
  126. if ((k & 0x80) == 0)
  127. hash ^= tab[i + 7];
  128. }
  129. return (hash & mask);
  130. }
  131. /**
  132. * Zobrist Hashing
  133. */
  134. public static int zobrist(char[] key, int mask, int[][] tab) {
  135. int hash, i;
  136. for (hash = key.length, i = 0; i < key.length; ++i)
  137. hash ^= tab[i][key[i]];
  138. return (hash & mask);
  139. }
  140. // LOOKUP3
  141. // 见Bob Jenkins(3).c文件
  142. // 32位FNV算法
  143. static int M_SHIFT = 0;
  144. /**
  145. * 32位的FNV算法
  146. *
  147. * @param data
  148. *            数组
  149. * @return int值
  150. */
  151. public static int FNVHash(byte[] data) {
  152. int hash = (int) 2166136261L;
  153. for (byte b : data)
  154. hash = (hash * 16777619) ^ b;
  155. if (M_SHIFT == 0)
  156. return hash;
  157. return (hash ^ (hash >> M_SHIFT)) & M_MASK;
  158. }
  159. /**
  160. * 改进的32位FNV算法1
  161. *
  162. * @param data
  163. *            数组
  164. * @return int值
  165. */
  166. public static int FNVHash1(byte[] data) {
  167. final int p = 16777619;
  168. int hash = (int) 2166136261L;
  169. for (byte b : data)
  170. hash = (hash ^ b) * p;
  171. hash += hash << 13;
  172. hash ^= hash >> 7;
  173. hash += hash << 3;
  174. hash ^= hash >> 17;
  175. hash += hash << 5;
  176. return hash;
  177. }
  178. /**
  179. * 改进的32位FNV算法1
  180. *
  181. * @param data
  182. *            字符串
  183. * @return int值
  184. */
  185. public static int FNVHash1(String data) {
  186. final int p = 16777619;
  187. int hash = (int) 2166136261L;
  188. for (int i = 0; i < data.length(); i++)
  189. hash = (hash ^ data.charAt(i)) * p;
  190. hash += hash << 13;
  191. hash ^= hash >> 7;
  192. hash += hash << 3;
  193. hash ^= hash >> 17;
  194. hash += hash << 5;
  195. return hash;
  196. }
  197. /**
  198. * Thomas Wang的算法,整数hash
  199. */
  200. public static int intHash(int key) {
  201. key += ~(key << 15);
  202. key ^= (key >>> 10);
  203. key += (key << 3);
  204. key ^= (key >>> 6);
  205. key += ~(key << 11);
  206. key ^= (key >>> 16);
  207. return key;
  208. }
  209. /**
  210. * RS算法hash
  211. */
  212. public static int RSHash(String str) {
  213. int b = 378551;
  214. int a = 63689;
  215. int hash = 0;
  216. for (int i = 0; i < str.length(); i++) {
  217. hash = hash * a + str.charAt(i);
  218. a = a * b;
  219. }
  220. return (hash & 0x7FFFFFFF);
  221. }
  222. /* End Of RS Hash Function */
  223. /**
  224. * JS算法
  225. */
  226. public static int JSHash(String str) {
  227. int hash = 1315423911;
  228. for (int i = 0; i < str.length(); i++) {
  229. hash ^= ((hash << 5) + str.charAt(i) + (hash >> 2));
  230. }
  231. return (hash & 0x7FFFFFFF);
  232. }
  233. /* End Of JS Hash Function */
  234. /**
  235. * PJW算法
  236. */
  237. public static int PJWHash(String str) {
  238. int BitsInUnsignedInt = 32;
  239. int ThreeQuarters = (BitsInUnsignedInt * 3) / 4;
  240. int OneEighth = BitsInUnsignedInt / 8;
  241. int HighBits = 0xFFFFFFFF << (BitsInUnsignedInt - OneEighth);
  242. int hash = 0;
  243. int test = 0;
  244. for (int i = 0; i < str.length(); i++) {
  245. hash = (hash << OneEighth) + str.charAt(i);
  246. if ((test = hash & HighBits) != 0) {
  247. hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));
  248. }
  249. }
  250. return (hash & 0x7FFFFFFF);
  251. }
  252. /* End Of P. J. Weinberger Hash Function */
  253. /**
  254. * ELF算法
  255. */
  256. public static int ELFHash(String str) {
  257. int hash = 0;
  258. int x = 0;
  259. for (int i = 0; i < str.length(); i++) {
  260. hash = (hash << 4) + str.charAt(i);
  261. if ((x = (int) (hash & 0xF0000000L)) != 0) {
  262. hash ^= (x >> 24);
  263. hash &= ~x;
  264. }
  265. }
  266. return (hash & 0x7FFFFFFF);
  267. }
  268. /* End Of ELF Hash Function */
  269. /**
  270. * BKDR算法
  271. */
  272. public static int BKDRHash(String str) {
  273. int seed = 131; // 31 131 1313 13131 131313 etc..
  274. int hash = 0;
  275. for (int i = 0; i < str.length(); i++) {
  276. hash = (hash * seed) + str.charAt(i);
  277. }
  278. return (hash & 0x7FFFFFFF);
  279. }
  280. /* End Of BKDR Hash Function */
  281. /**
  282. * SDBM算法
  283. */
  284. public static int SDBMHash(String str) {
  285. int hash = 0;
  286. for (int i = 0; i < str.length(); i++) {
  287. hash = str.charAt(i) + (hash << 6) + (hash << 16) - hash;
  288. }
  289. return (hash & 0x7FFFFFFF);
  290. }
  291. /* End Of SDBM Hash Function */
  292. /**
  293. * DJB算法
  294. */
  295. public static int DJBHash(String str) {
  296. int hash = 5381;
  297. for (int i = 0; i < str.length(); i++) {
  298. hash = ((hash << 5) + hash) + str.charAt(i);
  299. }
  300. return (hash & 0x7FFFFFFF);
  301. }
  302. /* End Of DJB Hash Function */
  303. /**
  304. * DEK算法
  305. */
  306. public static int DEKHash(String str) {
  307. int hash = str.length();
  308. for (int i = 0; i < str.length(); i++) {
  309. hash = ((hash << 5) ^ (hash >> 27)) ^ str.charAt(i);
  310. }
  311. return (hash & 0x7FFFFFFF);
  312. }
  313. /* End Of DEK Hash Function */
  314. /**
  315. * AP算法
  316. */
  317. public static int APHash(String str) {
  318. int hash = 0;
  319. for (int i = 0; i < str.length(); i++) {
  320. hash ^= ((i & 1) == 0) ? ((hash << 7) ^ str.charAt(i) ^ (hash >> 3)) : (~((hash << 11) ^ str.charAt(i) ^ (hash >> 5)));
  321. }
  322. // return (hash & 0x7FFFFFFF);
  323. return hash;
  324. }
  325. /* End Of AP Hash Function */
  326. /**
  327. * JAVA自己带的算法
  328. */
  329. public static int java(String str) {
  330. int h = 0;
  331. int off = 0;
  332. int len = str.length();
  333. for (int i = 0; i < len; i++) {
  334. h = 31 * h + str.charAt(off++);
  335. }
  336. return h;
  337. }
  338. /**
  339. * 混合hash算法,输出64位的值
  340. */
  341. public static long mixHash(String str) {
  342. long hash = str.hashCode();
  343. hash <<= 32;
  344. hash |= FNVHash1(str);
  345. return hash;
  346. }
  347. /**
  348. * 计算sha1
  349. *
  350. * @param text
  351. *            文本
  352. * @return 字节数组
  353. * @throws Exception
  354. */
  355. public static byte[] sha1(String text) throws Exception {
  356. MessageDigest md;
  357. md = MessageDigest.getInstance("SHA-1");
  358. byte[] sha1hash = new byte[40];
  359. byte[] input = text.getBytes("utf-8");
  360. md.update(input, 0, input.length);
  361. sha1hash = md.digest();
  362. return sha1hash;
  363. }
  364. // 4位值对应16进制字符
  365. static char[] m_byteToHexChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  366. /**
  367. * 计算sha1
  368. *
  369. * @param text
  370. *            文本
  371. * @return 16进制表示的hash值
  372. * @throws Exception
  373. */
  374. public static String sha1_text(String text) throws Exception {
  375. byte[] hash = sha1(text);
  376. StringBuilder ret = new StringBuilder(hash.length * 2);
  377. for (byte b : hash) {
  378. int d = (b & 0xff);
  379. ret.append(m_byteToHexChar[(d & 0xf)]);
  380. d >>= 4;
  381. ret.append(m_byteToHexChar[(d & 0xf)]);
  382. }
  383. return ret.toString();
  384. }
  385. }

应用Hash函数的更多相关文章

  1. Hash 函数及其重要性

    不时会爆出网站的服务器和数据库被盗取,考虑到这点,就要确保用户一些敏感数据(例如密码)的安全性.今天,我们要学的是 hash 背后的基础知识,以及如何用它来保护你的 web 应用的密码. 申明 密码学 ...

  2. Bitset<>用于unordered container时的默认hash函数

    自从c++11起,bitset用于unordered container,将会提供默认的hash函数. 在gcc中,相关代码如下: // DR 1182. /// std::hash speciali ...

  3. Hash函数及其应用

    本文部分内容摘自网络,参考资料链接会在文后给出,在此感谢原作者的分享. 计算理论中,没有Hash函数的说法,只有单向函数的说法.所谓的单向函数,是一个复杂的定义,大家可以去看计算理论或者密码学方面的数 ...

  4. 各种字符串Hash函数比较(转)

    常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...

  5. hash函数为什么要选择对素数求余?

    常用的hash函数是选一个数m取模(余数),这个数在课本中推荐m是素数,但是经常见到选择m=2^n,因为对2^n求余数更快,并认为在key分布均匀的情况下,key%m也是在[0,m-1]区间均匀分布的 ...

  6. 理解php Hash函数,增强密码安全

    1.声明 密码学是一个复杂的话题,我也不是这方面的专家.许多高校和研究机构在这方面都有长期的研究.在这篇文章里,我希望尽量使用简单易懂的方式向你展示一种安全存储Web程序密码的方法. 2.“Hash” ...

  7. 长度有限制的字符串hash函数

    长度有限制的字符串hash函数 DJBHash是一种非常流行的算法,俗称"Times33"算法.Times33的算法很简单,就是不断的乘33,原型如下 hash(i) = hash ...

  8. [转]各种字符串Hash函数比较

    转自:https://www.byvoid.com/zht/blog/string-hash-compare 常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些 ...

  9. 学习hash_map从而了解如何写stl里面的hash函数和equal或者compare函数

    ---恢复内容开始--- 看到同事用unordered_map了所以找个帖子学习学习 http://blog.sina.com.cn/s/blog_4c98b9600100audq.html (一)为 ...

  10. Hash函数的安全性

    我们为了保证消息的完整性,引进了散列函数,那么散列函数会对安全正造成什么影响呢?这是需要好好研究一番的问题. 三个概念: 1.如果y<>x,且h(x)=h(y),则称为碰撞. 2.对于给定 ...

随机推荐

  1. LeetCode - 13. Roman to Integer - 思考if-else与switch的比较 - ( C++ ) - 解题报告

    1.题目: 原题:Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range ...

  2. Entity Framework 基本概念

    概念 LINQ to Entities 一种 LINQ 技术,使开发人员可以使用 LINQ 表达式和 LINQ 标准查询运算符,针对实体数据模型 (EDM) 对象上下文创建灵活的强类型化查询. ESQ ...

  3. 2019-1-7Xiaomi Mi5 刷全球版MIUI教程

    2019-1-7Xiaomi Mi5 刷全球版MIUI教程 mi5 教程 小书匠  欢迎走进zozo的学习之旅. 前言 固件下载 刷机 刷recovery,root 试用体验 其他参考 前言 机器是老 ...

  4. Pipeline组Beta版本发布说明

    项目名称 Pipeline 项目版本 Beta版本 负责人 北京航空航天大学计算机学院 IloveSE 小组 联系方式 http://www.cnblogs.com/IloveSE 要求发布日期 20 ...

  5. <Effective C++>读书摘要--Accustoming Youself to C++

    <Item 1>View C++ as a federation of languages. 1.把C++看成4种子语言组成,即C.Object-Oriented C++.Template ...

  6. ZOJ 1913 J-Eucild's Game

    https://vjudge.net/contest/67836#problem/J Two players, Stan and Ollie, play, starting with two natu ...

  7. 移动端的picker参考vux

    参考vux移动端的ui组件,做了一个picker,测试在微信,uc主流浏览器能够正常工作.而在华为浏览器根本不能使用.而测试了vux的原有picker组件,发现在华为自带浏览器中,效果依然能够实现. ...

  8. django 安装/部署过程

    一.软件安装 1.升级linux中的python   参考“centos升级python” 2.安装apache(httpd) 3.安装django,先要安装setuptools    参考“安装dj ...

  9. 简述在akka中发送消息的过程

    在flink的数据传输过程中,有两类数据,一类数据是控制流数据,比如提交作业,比如连接jm,另一类数据是业务数据.flink对此采用了不同的传输机制,控制流数据的传输采用akka进行,业务类数据传输在 ...

  10. [计算机网络-应用层] DNS:因特网的目录服务

    我们知道有两种方式可以识别主机:通过主机名或者IP地址.人们喜欢便于记忆的主机名标识,而路由器则喜欢定长的.有着层次结构的IP地址.为了折中这些不同的偏好,我们需要一种能进行主机名到IP地址转换的目录 ...