在实际的工作中我们经常会用到hashCode,不管是简单哈希还是一致性哈希,底层的哈希算法都是一样的,今天参考源码做一个回顾:
先看hashCode的源码:
/**
* Returns a hash code for this string. The hash code for a
* {@code String} object is computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote>
* using {@code int} arithmetic, where {@code s[i]} is the
* <i>i</i>th character of the string, {@code n} is the length of
* the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
其中最重要的核心算法逻辑就是注释中的一行:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
以下是自己做的一个Demo来验证hashCode是如何产生的?
package com.google;
/**
* @Author: ♞Demons♕
* @DATE: 2018/11/9 11:01
* @Description: hashCode的实现
* 哈希算法的公式 : s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* n表示将字符串切分成字符数组后的字符的个数
* s[n]表示字符数组下标是n的字符的ASCII码
*/
public class TestHash {
public static void main(String[] args) {
String hashCode = "22";
// 2的ASCII码是:50,故22的hashCode的值是:50*31^1 + 50*31^0 = 1600
System.out.println(hashCode.hashCode());
// 实际使用中常使用hashCode的正数形式,可用这种形式转换
System.out.println(Math.abs(hashCode.hashCode()));
String code = "code";
// code中的每个字符的ASCII码分别是:99-111-100-101,
// 故code的hashCode的值是:99*31^3 + 111*31^2 + 100*31^1 + 101 = 3059181
System.out.println(code.hashCode());
}
}
至于为什么是31这个神奇的数字?可以参考这个博客:
https://blog.youkuaiyun.com/steveguoshao/article/details/12576849