java 关于Map的key可不可以是自定义对象的学习
以前写过一篇文章,当时写的不明确,对大家有点误导了,各位大神指点,我还是重写写一下我当时的想法,好几年前的了哈哈,不好意思。
场景:
因为我们在平时用map的时候,key是唯一的,比如一个map对应的key是个字符串,比如第一次我存入了下边这样的数据:
假如我下次又对key为a的数据去赋值为222
,很简单,肯定会被后来的数据给冲掉,变成了下边这样:
以上很好理解了,会java的都明白这个。
对象当key的问题:
map
是可以根据使用泛型,定义不同的类型当做key的,当然包括对象,比如下边这样,我定义了一个Student
类:
package org.app.mrms.filter;
/**
* Created by lingsf on 2019/4/27.
*/
public class Student {
private String name;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
然后定义几个Student
对象当做key
存到map
里:
package org.app.mrms.filter;
import java.util.HashMap;
import java.util.Map;
/**
* Created by lingsf on 2019/4/27.
*/
public class TestStudentMap {
public static void main(String[] args){
Map<Student,String> map = new HashMap();
Student a = new Student();
a.setName("一号");
a.setSex("男");
Student b = new Student();
b.setName("二号");
b.setSex("女");
map.put(a, "123");
map.put(b, "111"); //往map里放了两对数据
for(Student s:map.keySet()){
System.out.println("map中含有的数据:"+map.get(s));
}
System.out.println("map中获取对象a:"+map.get(a)); //试了试单独根据key获取值
System.out.println("map中获取对象b:"+map.get(b)); //试了试单独根据key获取值
System.out.println("存入两个对象之后==========");
Student c = new Student();
c.setName("一号");
c.setSex("男");
System.out.println("map中获取内容:"+map.get(c)); //因为c和a一样,我希望拿到a对应的数据
map.put(c,"222");
System.out.println("再存入一个c,c对象的姓名和性别,与a对象的一模一样");
System.out.println("map中获取对象c:"+map.get(c));
System.out.println("map中获取对象b:"+map.get(b));
System.out.println("map中获取对象a:"+map.get(a));
}
}
输出结果如下:
map中含有的数据:123
map中含有的数据:111
map中获取对象a:123
存入两个对象之后==========
map中获取内容:null
再存入一个c,c对象的姓名和性别,与a对象的一模一样
map中获取对象c:222
map中获取对象b:111
map中获取对象a:123
按照我们正常的做法,以上输出没有问题,因为现在map中对应存放了三个不同的对象当做key,所以对应的输出,很正确。
我现在的需求是这样:
1、因为c对象的姓名和性别,与a对象的一模一样,所以它们俩应该是当做同一个key,放到map里,即实现c存入map后能替换掉原来的a。
2、因为c对象的姓名和性别,与a对象的一模一样,所以它们俩应该是当做同一个key,当我根据new出来的c,直接去map里去get的时候,应该能拿到a对应的value。
总之一句话,达到在这个map里,c就是a,a就是c。
分析原因:
虽然c对象其中的姓名和性别与a的相同,但是毕竟它们两个是不同的对象,对于map中存取值,都是依据key的hashcode
值,通过计算后存到对应的桶里。因为默认的hashcode
值计算方式,与对象的地址有一定的联系,所以,不同的对象计算出来的hashcode
值一般也不会相同,所以在取值存值的时候会像上边一样。
解决方法:
只要我们做到让a和c能是一个人就解决了这个问题,map也就会把它俩当做一个人。既然map的存取值的“门票”是hashcode
值、equals
方法,那我们就重写我们这个对象的这两个方法,让它们一样就可以了。如下对Student
类重写hashcode
、equals
方法:
package org.app.mrms.filter;
/**
* Created by lingsf on 2019/4/27.
*/
public class Student {
private String name;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
//重写hashcode方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((sex == null) ? 0 : sex.hashCode());
return result;
}
//重写equals方法
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (sex == null) {
if (other.sex != null)
return false;
} else if (!sex.equals(other.sex))
return false;
return true;
}
}
&emsp;然后再去尝试运行上边的TestStudentMap
类,即会有下边的结果:
map中含有的数据:123
map中含有的数据:111
map中获取对象a:123
map中获取对象b:111
存入两个对象之后==========
map中获取内容:123
再存入一个c,c对象的姓名和性别,与a对象的一模一样
map中获取对象c:222
map中获取对象b:111
map中获取对象a:222 //c存入之后,a对应的值也被替换掉了
这样就达到了对象当做key的需求了。
是个比较简单的方法,我以前没描述清楚,希望这个能描述清楚。