借鉴:https://blog.csdn.net/asd991543753/article/details/105951767
https://blog.csdn.net/weixin_44507219/article/details/120292543
一:HashMap同时重写hashCode和equals方法的原因
1.Object类中hashCode方法和equals方法:
//是用native修饰的,也就是默认由操作系统实现,即hashcode值默认是由通过内存中的引用计算得出的;
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
2.HashMap重写equals方法:目的是比较两个map的key和value是否都相等
如果不重写,则是比较两个对象map的地址是否相等,除非两个对象真一样会返回true;但如果是两个new的不同的map就算key和value都相等返回的还是false
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map))
return false;
Map<?,?> m = (Map<?,?>) o;
if (m.size() != size())
return false;
try {
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext()) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
if (value == null) {
if (!(m.get(key)==null && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
}
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
return true;
}
3.HashMap重写hashCode方法:
(1):put (“a” ,“123”) ; —> 存这个的时候调用key 的hashCode , 因为Object的hashcode返回的是内存地址 ,如果不重写hashcode , 那么同样的一个键值对 , 唯一性得不到保证 。
(2):假设上方put (“a” ,“123”) ; put成功 ,如果这个时候继续调用一次put (“a” ,“123”) ;那么如果没有重写hashCode , 则此时两者都用的Object的hashcode去返回内存地址 , 两者hashcode比较肯定是不同的 ,原因在于不是同一个对象 。没有重写的话,就会有两条数据 (“a” ,“123”) ,违背了HashMap的key不重复的特点
内部类Node中重写了hashCode():
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
}