快来,我悄悄的给你说几个HashCode的破事。 (4)

简介: 快来,我悄悄的给你说几个HashCode的破事。 (4)

实体类当做 key


上面的示例中,我们用的是 String 类型当做 HashMap 中的 key。


这个场景能覆盖我们开发场景中的百分之 95 了。


但是偶尔会有那么几次,可能会把实体类当做 key 放到 HashMap 中去。


注意啊,面试题又来了:在 HashMap 中可以用实体类当对象吗?


那必须的是可以的啊。但是有坑,注意别踩进去了。


我拿前段时间看到的一个新闻给大家举个例子吧:


image.png


假设我要收集学生的家庭信息,用 HashMap 存起来。


那么我的 key 是学生对象, value 是学生家庭信息对象。


他们分别是这样的:


public class HomeInfo {
    private String homeAddr;
    private String carName;
     //省略改造方法和toString方法
}
public class Student {
    private String name;
    private Integer age;
     //省略改造方法和toString方法
}


然后我们的测试用例如下:


public class HashMapTest {
    private static Map<Student, HomeInfo> hashMap = new HashMap<Student, HomeInfo>();
    static {
        Student student = new Student("why", 7);
        HomeInfo homeInfo = new HomeInfo("大南街", "自行车");
        hashMap.put(student, homeInfo);
    }
    public static void main(String[] args) {
        updateInfo("why", 7, "滨江路", "摩托");
        for (Map.Entry<Student, HomeInfo> entry : hashMap.entrySet()) {
            System.out.println(entry.getKey()+"-"+entry.getValue());
        }
    }
    private static void updateInfo(String name, Integer age, String homeAddr, String carName) {
        Student student = new Student(name, age);
        HomeInfo homeInfo = hashMap.get(student);
        if (homeInfo == null) {
            hashMap.put(student, new HomeInfo(homeAddr, carName));
        }
    }
}


初始状态下,HashMap 中已经有一个名叫 why 的 7 岁小朋友了,他家住大南街,家里的交通工具是自行车。


然后,有一天他告诉老师,他搬家了,搬到了滨江路去,而且家里的自行车换成了摩托车。


于是老师就通过页面,修改了 why 小朋友的家庭信息。


最后调用到了 updateInfo 方法。


嘿,你猜怎么着?


我带你看一下输出:


image.png


更新完了之后,他们班上出现了两个叫 why 的 7 岁小朋友了,一个住在大南街,一个住在滨江路。


更新变新增了,你说神奇不神奇?


现象出来了,那么根据现象定位问题代码不是手到擒来的事儿?


很明显,问题就出在这个地方:


image.png


这里取出来的 homeInfo 为空了,所以才会新放一个数据进去。


那么我们看看为啥这里为空。


跟着 hashMap.get() 源码进去瞅一眼:


image.png


标号为 ① 的地方是计算 key ,也就是 student 对象的 hashCode。而我们 student 对象并没有重写 hashCode,所以调用的是默认的 hashCode 方法。


这里的 student 是 new 出来的:


image.png


所以,这个 student 的 hashCode 势必和之前在 HashMap 里面的 student 不是一样的。


因此,标号为 ③ 的地方,经过 hash 计算后得出的 tab 数组下标,对应的位置为 null。不会进入 if 判断,这里返回为 null。


那么解决方案也就呼之欲出了:重写对象的 hashCode 方法即可。


是吗?


等等,你回来,别拿着半截就跑。我话还没说完呢。


接着看源码:


image.png

目录
相关文章
|
8月前
|
存储 人工智能 JavaScript
编织魔法与修电脑:码农征途的奇妙起点
编织魔法与修电脑:码农征途的奇妙起点
89 0
|
安全 Java
快来,我悄悄的给你说几个HashCode的破事。 (2)
快来,我悄悄的给你说几个HashCode的破事。 (2)
149 1
快来,我悄悄的给你说几个HashCode的破事。 (2)
|
存储 算法 安全
工作三年,小胖连 HashMap 源码都没读过?真的菜!(下)
工作三年,小胖连 HashMap 源码都没读过?真的菜!
工作三年,小胖连 HashMap 源码都没读过?真的菜!(下)
|
算法 Java
工作三年,小胖连 HashMap 源码都没读过?真的菜!(上)
工作三年,小胖连 HashMap 源码都没读过?真的菜!
工作三年,小胖连 HashMap 源码都没读过?真的菜!(上)
|
存储 JSON JavaScript
听说你情人节没人陪,这不我来给你介绍对象啦
听说你情人节没人陪,这不我来给你介绍对象啦
237 0
听说你情人节没人陪,这不我来给你介绍对象啦
|
Java
快来,我悄悄的给你说几个HashCode的破事。 (5)
快来,我悄悄的给你说几个HashCode的破事。 (5)
115 0
快来,我悄悄的给你说几个HashCode的破事。 (5)
|
算法 Java
快来,我悄悄的给你说几个HashCode的破事。 (1)
快来,我悄悄的给你说几个HashCode的破事。 (1)
132 0
快来,我悄悄的给你说几个HashCode的破事。 (1)
|
Java 测试技术
快来,我悄悄的给你说几个HashCode的破事。 (3)
快来,我悄悄的给你说几个HashCode的破事。 (3)
99 0
快来,我悄悄的给你说几个HashCode的破事。 (3)
|
人工智能 前端开发 算法
为了帮学弟学妹找免费编程资源,真是操碎了心!
为了帮学弟学妹找免费编程资源,真是操碎了心!
183 0
为了帮学弟学妹找免费编程资源,真是操碎了心!

热门文章

最新文章