蔚來(lái)一面:用Object做hashMap的Key時(shí)需要做什么?

作者 | petterp
先來(lái)說(shuō)一下hashcode()和equals方法吧。
hashcode()
hashCode 的存在主要用于查找的快捷性,如 Hashtable, HashMap 等,hashCode 是用來(lái)在三列存儲(chǔ)結(jié)構(gòu)中確定對(duì)象的存儲(chǔ)地址的。 如果兩個(gè)對(duì)象相同,就是適用于 euqals(java.lang.Object) 方法,那么這兩個(gè)對(duì)象的 hashCode一定相同。 如果對(duì)象的euqals 方法被重寫(xiě),那么對(duì)象的 hashCode 也盡量重寫(xiě),并且產(chǎn)生 hashCode 使用的對(duì)象,一定要和 equals 方法中使用的一致,否則就會(huì)違反上面提到的第二點(diǎn)。 兩個(gè)對(duì)象的 hashCode 相同,并不一定表示這兩個(gè)對(duì)象就相同,也就是不一定適用于equals() 方法,只能夠說(shuō)明這兩個(gè)對(duì)象在三列存儲(chǔ)結(jié)構(gòu)中,如 Hashtable.,他們存在同一個(gè)籃子里。以上話以前摘錄自一篇博客,講的非常好。
equals(Object obj)
如果一個(gè)類沒(méi)有重寫(xiě) equals(Object obj)方法,則等價(jià)于通過(guò) == 比較兩個(gè)對(duì)象,即比較的是對(duì)象在內(nèi)存中的空間地址是否相等。 如果重寫(xiě)了equals(Object ibj)方法,則根據(jù)重寫(xiě)的方法內(nèi)容去比較相等,返回 true 則相等,false 則不相等。
我用一個(gè)簡(jiǎn)單的demo來(lái)舉個(gè)例子吧.
public class MyClass {
public static void main(String[] args) {
HashSet books=new HashSet();
books.add(new A());
books.add(new A());
books.add(new B());
books.add(new B());
books.add(new C());
books.add(new C());
System.out.println(books);
}
}
class A{
//類A的 equals 方法總是返回true,但沒(méi)有重寫(xiě)其hashCode() 方法
@Override
public boolean equals(Object o) {
return true;
}
}
class B{
//類B 的hashCode() 方法總是返回1,但沒(méi)有重寫(xiě)其equals()方法
@Override
public int hashCode() {
return 1;
}
}
class C{
public int hashCode(){
return 2;
}
@Override
public boolean equals(Object o) {
return true;
}
}
結(jié)果
即使兩個(gè)A 對(duì)象通過(guò) equals() 比較返回true,但HashSet 依然把他們當(dāng)成 兩個(gè)對(duì)象,即使兩個(gè) B 對(duì)象 的hashCode() 返回值相同,但HashSet 依然把他們當(dāng)成兩個(gè)對(duì)象。 即也就是,當(dāng)把一個(gè)對(duì)象放入HashSet 中時(shí),如果需要重寫(xiě)該對(duì)象對(duì)應(yīng)類的 equals() 方法,則也應(yīng)該重寫(xiě)其 hashCode() 方法。規(guī)則是:如果兩個(gè)對(duì)象通過(guò) equals() 方法比較返回true,這兩個(gè)對(duì)象的 hashCode 值也應(yīng)該相同。 如果兩個(gè)對(duì)象通過(guò)euqals() 方法比較返回true,但這兩個(gè)對(duì)象的 hashCode() 方法返回不同的hashCode 值時(shí),這將導(dǎo)致HashSet 會(huì)把這兩個(gè)對(duì)象保存在 Hash 表的不同位置,從而使兩個(gè)對(duì)象都可以添加成功,這就與 Set 集合的規(guī)則沖突了。 如果兩個(gè)對(duì)象的 hashCode() 方法返回的 hasCode 值相同,但他們通過(guò) equals() 方法比較返回false 時(shí)將更麻煩:因?yàn)閮蓚€(gè)對(duì)象的hashCode 值相同,HashSet 將試圖 把它們保存在同一個(gè)位置,但又不行(否則將只剩下一個(gè)對(duì)象),所以實(shí)際上會(huì)在這個(gè)位置用鏈?zhǔn)浇Y(jié)構(gòu)來(lái)保存多個(gè)對(duì)象;而HashSet 訪問(wèn)集合元素時(shí)也是根據(jù)元素的 hashCode 值來(lái)快速定位的,如果 hashSet 中兩個(gè)以上的元素具有相同的 HashCode 值時(shí),將會(huì)導(dǎo)致性能下降。
用Object做hashMap的Key時(shí)需要做什么?
用自定義類作為key,必須重寫(xiě)equals()和hashCode()方法。
自定義類中的equals() 和 hashCode()都繼承自O(shè)bject類。
1. Nginx 入門(mén)到實(shí)戰(zhàn),新手必懂~
3. 終于搞懂了Java 8 的內(nèi)存結(jié)構(gòu),再也不糾結(jié)方法區(qū)和常量池了??!
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。
獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。
謝謝支持喲 (*^__^*)
評(píng)論
圖片
表情

