1. 程式人生 > >重新對equals與hashcode的理解

重新對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分別比的是什麼?

這兩個只不過是解決兩個物件是否想等的兩個策略或者兩個形式,只不過比較的方式不同,互相依賴也不依賴。

感覺我說的有問題的朋友請求騷擾。