关于HashMap<k,v>的一些坑

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

一、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时的对象属性值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值