1、java.lang.Object中的源码
public boolean equals(Object obj) {
return (this == obj);
}
public native int hashCode();
可以看出,equals方法内部调用的==号,比较的两个对象的引用地址。
hashCode()则是一个本地方法,返回的是一个内存地址。
2、代码分析
public class Test {
public static void main(String[] args) {
Person key1 = new Person("周瑜");
Person key2 = new Person("周瑜");
Map<Person,String> map = new HashMap<>();
map.put(key1,"大乔");
map.put(key2,"小乔");
for(Map.Entry<Person,String> m : map.entrySet()){
System.out.println(
"key:" + m.getKey() + " value:" + m.getValue());
}
}
/**
* 静态内部类
*/
static class Person{
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
}
分析代码:
- 按照hashMap的正常规则,(key2,v2)会覆盖掉(key1,v1)。
- 如果不重写这两个方法,key1和key2的hashcode值会不同,所以两个键值对都会存放到不同桶的位置。不符合预期
- 如果重写equals(),不重写hashCode(),所以两个键值对都会存放到不同桶的位置。不符合预期.
- 如果重写hashCode(),不重写equals(), key1和key2会以链表的形式放到同一个桶的位置。不符合预期
使用hashMap时,如果key是自定义的类,一定要重写hashcode()和equals()。因为hashMap是使用链表与数组结合的方式来存储数据的。