阶段三 · 哈希表和 SQRT 分解-1.3 JAVA中hashcode方法
老师,你好!
这里有一个疑问,B不能随便取吧,应该取 grade的所有组合*cls的所有组合*firstname的所有组合*lastname的所有组合吧
正在回答 回答被采纳积分+1
首先,如果完全把 {grade, cls, firstName.hashCode} 当做 B 进制数看待的话,B 的取值应该是 max(grade, cls, firstName.hashCode) + 1。
比如,第一个域的取值范围是 0-3, 第二个域的取值范围是 0-10,第三个域的取值范围是 0-999。那么,1000 进制的数就可以完整表示所有这三个域的所有可能。(而不是将他们做乘法)
==========
但最重要的是,哈希值不完全是把一个对象的所有域严格当做一个 B 进制数看待,而是借用这种计算方式,计算出一个整数当做哈希值。
评判一个哈希值好坏的方式,不是他是不是一个严谨的 B 进制数,而是这样计算获得的哈希值,哈希冲突的概率的高低。(具体怎么计算这个概率,已经远超这个课程,甚至远超大多数计算机专业课程的范围了。)
在这里,我举例用 B = 31,其实是有原因的。因为在 Java 中,字符串哈希用的 B 的值,就是 31。(而很显然,字符的取值范围是超过 31 的)。
你可以尝试以下代码,其中的 my_hash() 就是用 B = 31 把 s 当做 31 进制的数字看待做计算的模拟(虽然每个域的取值可能超过 30。)。hash_code 则得到 Java 内置的字符串的哈希值。你可以看到,在短字符串下(因为这个模拟没有做溢出处理,只是一个模拟),他们的打印结果是相同的。
public class HashTest { private static long my_hash(String s){ long res = 0; for(char c: s.toCharArray()) res = res * 31 + c; return res; } public static void main(String[] args) { String s1 = "ABC"; System.out.println(s1.hashCode()); System.out.println(HashTest.my_hash(s1)); String s2 = "imooc"; System.out.println(s2.hashCode()); System.out.println(HashTest.my_hash(s2)); } }
继续加油!:)
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星