重新對equals與hashcode的理解
之前看面試題的時候發現了一個遺忘的知識點,就是hashcode()與equals().
忽然之間弄不明白hashcode與equals分別比的是什麼?誰先執行?什麼情況下都執行?什麼情況下都只執行一個?
為了弄懂這些我特意去網上查閱了大量的部落格與文章。發現了都是講概念不講原理,空口套話誰不會,如果概念再加上實質的理解豈不更好?所以今天就寫了這篇文章,當然內容肯定也有不妥的地方還希望網友指出,討論,咱們共同進步一起成長。
好,不多說!我們先記住一段話“equals()==true則hashcode()==true,hashcode()==true則不一定equals()==true”
那麼我們就不去object查詢原始碼了,因為這會誤導我們的思維。我們看一下我們重寫之後的程式碼吧:
public class Users { private String username; private String password; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((password == null) ? 0 : password.hashCode()); result = prime * result + ((username == null) ? 0 : username.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Users other = (Users) obj; if (password == null) { if (other.password != null) return false; } else if (!password.equals(other.password)) return false; if (username == null) { if (other.username != null) return false; } else if (!username.equals(other.username)) return false; return true; } }
網上有人說hashcode比較的實地址,但又一老說 “equals()==true則hashcode()==true,hashcode()==true則不一定equals()==true”,當時我就十分費解,難道兩個內容一樣的物件要存在一個地址空間嗎,這不就成了同一個物件了嗎,但我們確實是new的不同的物件,當時我就不停的想啊想啊,還是想不明白,後來要不看一下原始碼吧,發現也沒多大用處,那就自己寫一個類重寫這裡邊的方法看看他的重寫過程,發現一下子解開了我的疑惑。
我們看這個hashcode究竟做了什麼事
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((password == null) ? 0 : password.hashCode()); result = prime * result + ((username == null) ? 0 : username.hashCode()); return result; }
我們發現他並沒有去比較地址而是返回物件中的內容的hash值。那麼我們再看看equals吧:
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Users other = (Users) obj;
if (password == null) {
if (other.password != null)
return false;
} else if (!password.equals(other.password))
return false;
if (username == null) {
if (other.username != null)
return false;
} else if (!username.equals(other.username))
return false;
return true;
}
發現他也是對物件內容進行比較,那我們實現equals時候必須實現hashcode嗎,答案是可以不實現,但建議實現為啥那麼那?
我們執行流程的時候發現,當有hashcode重寫實現的時候或者走object的hashcode方法的時候進行物件間比較程式總是先走hashcode然後走equals,其中equals不是必須走的而是當兩個物件比較的hash值一直的時候才會走。為啥會這樣那?
我們都知道機器底層其實識別的只有01程式碼,那麼他處理hash值得速度是不是更快一些那,對系統性能也就提高一點了,而由於轉換為hash值可能會重複的比如“2+4==3+3”,所以equals就是當前面的方法解決不了問題了才會登場。這也就很好的解釋了前面的一句話“equals()==true則hashcode()==true,hashcode()==true則不一定equals()==true“
那麼我們就知道誰先執行了?為了效能當然先執行hashcode;
什麼情況下都執行?當然是hashcode自己解決不了的時候,什麼時候解決不了看上邊;
什麼情況下只執行一個?當hashcode自己能夠解決的時候;
有沒有隻執行equals的時候?答案是沒有,就算你不去實現hashcode我們的老大object也有的,只不過返回永遠是一樣的所以“強制”去執行equals;
那麼到底hashcode與equals分別比的是什麼?
這兩個只不過是解決兩個物件是否想等的兩個策略或者兩個形式,只不過比較的方式不同,互相依賴也不依賴。
感覺我說的有問題的朋友請求騷擾。