hash和散列表在java中的作用

散列表/哈希表是存储记录的数据结构,哈希函数是关键字和存储位置的对应关系的映射函数,我们希望f(Key)得到不同哈希地址。但是一般总会有冲突存在。key是关键字的话,是由字母数字组成的,大约1.2x10^14,而实际中用不到那么多,哈希函数就是一个压缩映像。

Hash关键在于hash函数的选择和冲突解决。
好的hash函数是均匀的,就是尽量不要映射后存储位置聚集。

冲突解决当然很多,最常用的是开放定址法(包括三种探测再散列方法,就是微调一下散列函数,加一个步长di,重新找一个空位)和链地址法。

java的hashMap和hashTable就是使用链地址法。底层都是数组加链表。他俩区别是hashTable是线程安全的。
hashcode不是返回真实地址,是虚拟机映射的虚拟地址。key对象没有重写hashcode,value不会为null,重写hashcode对应的是动态数组中的值,hashcode不同直接就放数组了,hashcode相同就把元素放入链表中,key对象相同就覆盖value值。
有一篇博客部分解释了java中的hash和hashCode原理:
https://blog.csdn.net/qq_38182963/article/details/78940047
下面这篇博客讲解了为什么:对象的equals方法被重写,那么对象的hashCode也尽量重写。
https://blog.csdn.net/fenglibing/article/details/8905007

hashMap的博客参考这篇解释:
https://blog.csdn.net/ghsau/article/details/16843543

HashMap通过键的hashCode来快速的存取元素。
当不同的对象发生碰撞时,HashMap通过单链表来解决,将新元素加入链表表头,通过next指向原有的元素。单链表在Java中的实现就是对象的引用(复合)。

下面我自己调试了一下String计算hashcode的方法,因为hashMapo中一般key都是String类型嘛。

    @Test
    public void test(){
//        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//        CameraMapper mapper = ac.getBean(CameraMapper.class);
//        mapper.getCamByBingingFileId(1,4);
//        byte     1字节
//        short    2字节
//        int      4字节
//        long     8字节
//        char     2字节(C语言中是1字节)可以存储一个汉字
//        float    4字节
//        double   8字节
//        boolean  false/true(理论上占用1bit,1/8字节,实际处理按1byte处理)


        String str1 = "1";
        String str2 = "a";
        String str3 = str1+"a";
        System.out.println(str1.hashCode());
        System.out.println(str2.hashCode());
        System.out.println(str3.hashCode());
        char[] strChar=str3.toCharArray();
        String result="";
        for(int i=0;i<strChar.length;i++){
            result += Integer.toBinaryString(strChar[i])+ " ";
        }
        System.out.println(result);
    }



#结果:
49
97
1616
110001 1100001 

上面如果是单个字符,就是该字符的ASCII码值,多个字符按 str[0]31^(n-1) + str31^(n-2) + … + str[n-1] 公式计算, 这里str[i] 是第一个字符的ASCII码值,可以根据这个手算默认hashcode值。

1616 = 97+49*31,完全正确。

debug调试时在计算时很复杂,有很多轮迭代,暂时搞不懂源码咋跑的,不过上面的公式就是最终的结果。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值