阶段三 · 哈希表和 SQRT 分解-1.3 JAVA中hashcode方法

来源:1-3 Java中的hashCode方法

慕工程9558244

2021-12-18 11:22:25

https://img.mukewang.com/climg/61bd53ac09a0ea5706740193.jpg

老师,你好!

这里有一个疑问,B不能随便取吧,应该取  grade的所有组合*cls的所有组合*firstname的所有组合*lastname的所有组合吧

写回答

1回答

liuyubobobo

2021-12-18

首先,如果完全把 {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
hulu19
回复
hiuyubobobo
hp>好的,谢谢老师

h024-11-07
共3条回复

算法与数据结构

波波老师5年集大成之作,算法与数据结构系统学习,考试、面试、竞赛通用

2636 学习 · 1090 问题

查看课程