HashMap用可变对象作为key踩坑
前言
在Java道路上越踩越多坑,最近被问到一个知识点,当对象作为HashMap一个key时,再未重写equals
和hashcode
方法时候,get
方法返回的值为null
。
分析
在下面一段代码中,未重写equals以及hashCode方法情况下,输出结果为null
import java.util.HashMap;
import java.util.Map;
class People {
private String name;
public People() {
}
public People(String name) {
this.name = name;
}
public static void main(String[] args) {
Map<People, Integer> map = new HashMap<People, Integer>();
map.put(new People("icharle"), 18);
System.out.println(map.get(new People("icharle")));
}
}
# 输出结果为null
改造后代码:
import java.util.HashMap;
import java.util.Map;
class People {
private String name;
public People() {
}
public People(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
People people = (People) obj;
if (name != null ? !name.equals(people.name) : people.name != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
public static void main(String[] args) {
Map<People, Integer> map = new HashMap<People, Integer>();
map.put(new People("icharle"), 18);
System.out.println(map.get(new People("icharle")));
}
}
# 输出结果为18
原因分析
HashMap在查找某一个key时,先是用hashCode函数根据该key的地址计算,再用equals函数根据对象的地址进行比较。
- 在代码片段一中,
map.put(new People("icharle"), 18);
以及System.out.println(map.get(new People("icharle")));
中默认是两个对象(也就是说两个对象的地址不一样,自然hashcode函数得到的值是不一样(因为两个的对象的地址不同,自然在equals时候更不可能相等,最终得到的结果为null。 - 在代码片段二中,重载
hashCode()
函数的作用是:对于同一个key,得到相同的hash值,重载equals()
函数的作用是:向HashMap
表明当前对象和key上所保存的对象是相等的。因此该情况下最终结果为18