一、HashMap<k,v>中K为对象时:
首先我们定义一个Student类,属性有name(字符串),age(整数)。对象类型做为Map<k,v>泛型时,必须**重写hashCode()和equals() 方法**:
public class Student {
private String name;
private int age;
// getter和setter方法省略
// hashCode()和equals() 方法重写省略
}
main方法里,代码如下:
Student s1 = new Student();
HashMap<Student, String> h1 = new HashMap<>(16);// 初始长度设为16。 Map中Key为对象类型
s1.setAge(10); // 对象s1初试化
h1.put(s1, "s1");
System.out.println("通过key获取value: " + h1.get(s1));
s1.setAge(99);// 修改对象s1的属性值
System.out.println("通过key获取value: " + h1.get(s1));
打印输出结果竟然两次结果不一样:
- 通过key获取value: s1
- 通过key获取value: null
也就是修改对象的属性值后,map里居然找不到了。其实也很好理解,对象属性值变化后,就不是先前保存到Map里的那个对象了,map里没有保存改变后的对象,自然所对应的val就是null了。
**
那么有趣的事情就出现了,
我们·新new一个对象s2,并给它赋初值为1000;接下来,我们把s1的属性值改成map里已经存在的s2的属性值,
Student s2 = new Student();
s2.setAge(1000);
h1.put(s2, "s2");
System.out.println("通过key获取value: " + h1.get(s2));
s1.setAge(1000); // 对象s1属性值改为s2的
System.out.println("通过key获取value: " + h1.get(s1));
运行,奇怪的事情出现了,都是s2;
- 通过key获取value: s2
- 通过key获取value: s2
居然用s1获取到s2的val了,也即是说Map<K,V>中的K中存放的不是具体对象,而是对象中的具体属性值。
所以我估计这也就是Redis缓存数据库为什么Key只能存字符串类型的原因吧,(有其他想法的,评论区可以来深入探讨一下)。
二、那如果HashMap<k,v>中V为对象时呢?
OMG,val中存放的居然是对象的引用地址,对象更新后,get到的val也是对象的最新属性值。有点坑。
这里可以参考:求解释Map放入同一对象后的对象属性会被冲掉
这里就不贴出代码了,有兴趣的可以自己代码实现以下,看下效果。
拿java和go对比了下,K为对象时,效果一样;而V为对象时,go还是返回第一次put时的对象属性值。

本文探讨了Java中HashMap的使用特性,当K为对象时,必须重写hashCode()和equals()方法,且Map存储的是对象属性值而非对象本身。当V为对象时,Map存储的是对象引用,对象更新后,get到的值也会随之更新。
378

被折叠的 条评论
为什么被折叠?



