本文系转载,转自: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. 4-2:实现cp命令

    #include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h& ...

  2. Kprobe

    linux内核源码Documentation目录下存在kprobe介绍文档如下 Kprobes allows multiple probes at the same address.  Current ...

  3. <Effective C++>读书摘要--Designs and Declarations<二>

    <Item 20> Prefer pass-by-reference-to-const to pass-by-value 1.By default, C++ passes objects ...

  4. Uncaught ReferenceError: wx is not defined

    程序的分享功能调用了微信的接口,但是忽然发现就报这个错误, Uncaught ReferenceError: wx is not defined 同时下方还有这个错误 This content sho ...

  5. 如何将PDF的背景色设置为保护眼睛的苹果绿色

      福昕阅读器请戳这里.   Adobe Acrobat请戳这里.

  6. 多线程Worker初尝试

    多线程这个概念,不知道听了多少遍.但是真滴没有去实操过. 前几天看视频听到作者说道关注技术本身,而不是总写业务代码.这几天依然思考着这个问题.于是从头开始重现了html文件的堵塞问题,重现了html文 ...

  7. FineCMS介绍

      产品简介 FineCMS(简称免费版.企业版.公益版)是一款基于PHP+MySql+CI框架开发的高效简洁的中小型内容管理系统,面向多终端包括Pc端网页和移动端网页,支持自定义内容模型和会员模型, ...

  8. 在select中,载入时默认select为空白,选项内不显示空白项

    有两种办法,一种纯css实现,一种借助js实现. html: <body onload="load()"> <select id="abc" ...

  9. 【bzoj4922】[Lydsy六月月赛]Karp-de-Chant Number 贪心+背包dp

    题目描述 给出 $n$ 个括号序列,从中选出任意个并将它们按照任意顺序连接起来,求以这种方式得到匹配括号序列的最大长度. 输入 第一行包含一个正整数n(1<=n<=300),表示括号序列的 ...

  10. 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树

    题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...