一道关于哈希表的题目

一道关于哈希表的题目

老师你好这里有一道关于哈希表的题目但是我没想明白得到结果的过程


题目如下Assume that HashMap is a separate chaining hash table with 4 buckets indexed 0 through 3 and never resizes. Recall that get returns null if the key is not in the map.


相关代码

import java.util.HashMap;

public class Husky {
    public String name;

    public Husky(String name) {
        this.name = name;
    }

    public boolean equals(Object o) {
        Husky other = (Husky) o;
        return this.name.equals(other.name);
    }

    public int hashCode() {
        return this.name.length();
    }

    public static void main(String[] args) {
        HashMap<Husky, Integer> map = new HashMap<>();
        Husky a = new Husky("jeter");
        Husky b = new Husky("diana");

        map.put(a, 1);
        map.put(b, 2);

        a.name += a.name;
        map.put(a, 3);
        map.put(b, 4);

        b.name += b.name;
        map.put(b, 5);

        System.out.println(map.size());
        System.out.println(map.get(new Husky("jeter")));
        System.out.println(map.get(new Husky("jeterjeter")));
    }
}

结果是 4,  null, 3

我再intellij上跑了每个put 后面表的所有key和value但是我没懂为什么是那样

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
liuyubobobo 2021-10-30 11:05:55

我没有理解你具体不理解的点在哪里。


请阐述:在哪一句执行以后,你认为应该是什么结果?为什么?实际却是什么结果。所以你不理解。


==========


这个问题的核心有两个:


1)是:Husky 这个类的 hashcode 是 name.length,而不是 name。所以,在哈希表中,将首先以 name 的长度分组,name 的长度相同,则造成了哈希冲突,才会进一步比较具体的 name


2)是,当把一个元素存进哈希表以后,改变这个元素的 name,即使长度改变了,这个元素在哈希表中存储的位置不会跟着变。(哈希表没有实时更新,不会一遍一遍地扫描表内的元素,看这些元素是否发生了改变。)(所以,这样做是不安全的。)


所以:

map.put(a, 1) 和 map.put(b, 2) 后,更准确的记录是:


hashcode: 5 : {"jeter": 1} {"diana": 2}


其中 hashcode 5 表示哈希值是 5。因为 jeter 和 diana 的长度都是 5。


=========


之后,虽然有 a.name += a.name,但是,整个表变成了:


hashcode: 5 : {"jeterjeter": 1} {"diana": 2}



也就是哈希值为 5 的元素里,存了一个 name 长度为 10 的元素。


==========


之后,map.put(a 3),哈希表变成了


hashcode: 5 : {"jeterjeter": 1} {"diana": 2}
hashcode: 10: {"jeterjeter": 3}


此时,新加入了 jeterjeter 由于长度为 10,哈希值为 10,直接去哈希值为 10 的 bucket。在这里没有找到哈希冲突,直接加进去。


但是,map.put(b, 4),diana 可以正常找到,所以,哈希表变成了:

hashcode: 5 : {"jeterjeter": 1} {"diana": 4}
hashcode: 10: {"jeterjeter": 3}


==========



现在,你应该明白了 b.name += b.name 后,哈希表是:

hashcode: 5 : {"jeterjeter": 1} {"dianadiana": 4}
hashcode: 10: {"jeterjeter": 3}



map.put(b, 5) 后,是:

hashcode: 5 : {"jeterjeter": 1} {"dianadiana": 4}
hashcode: 10: {"jeterjeter": 3} {"dianadiana": 5}


请根据上面的哈希表的结果,再看最后打印输出的结果,应该很清晰。


值得一提的是最后一个打印输出,查询 jeterjeter,此时会按照 长度为 10 去查(而不是 5),所以得到的结果是 3。


继续加油!:)

  • 提问者 weixin_慕圣6334738 #1

    老师你好我看上面的代码是乱码所以我就用图片的形式先再吧代码给您看下

    https://img1.sycdn.imooc.com//climg/618077c309dddd5413001522.jpg

    下面这张图是每一步我在intellij上面跑出来的结果

    https://img1.sycdn.imooc.com//climg/6180782b09cb88f318700688.jpg

    首先我不太明白的点是第三行我在a.name += a.name后map里面的key 变成了jeterjeter那我猜测首先key是object所以它的name属性也跟着变了然后我不明白为什么jeterjeter的值就变成了null 倒数第二行也是同样的情况 而且为什么我用map.put(a, 3) 后map里面会同时出现两个key同时为jeterjeter的keyvalue pair这也是我不太明白的点


    最后有一个问题是这样的

    Why does map.get(new Husky("jeterjeter")) return 3?

    我知道result map也就是第二张图的最后一行 有两个 jeterjeter并且值都是3但是这里get里面传入了一个new Husky 不应该是新的对象吗为什么结果打印出来是3这个地方我也没有太明白


    感谢老师的耐心答复

    2021-11-02 07:34:57
  • liuyubobobo 回复 提问者 weixin_慕圣6334738 #2

    我补充在了原回答中。继续加油!:)

    2021-11-03 07:09:36
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星

相似问题

登录后可查看更多问答,登录/注册

算法与数据结构
  • 参与学习       2583    人
  • 解答问题       1082    个

慕课网算法名师Liuyubobobo,5年集大成之作 从0到工作5年,算法与数据结构系统解决方案

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师