hashcode() and equal()
equal方法Object類的equals方法用于檢測一個對象是否等于另外一個對象,而Object類中這個方法的定義為兩個對象是否具有相同的引用。源碼如下:
Java代碼
public boolean equals(Object obj) {
return (this == obj);
}
return (this == obj);
}
自反性:對于任何非空引用x,x,equal(x)應(yīng)該返回true
對稱性:對于任何引用x,x如果x.equal(y)返回true,那么y.equal(x)也應(yīng)該返回true
傳遞性:對于任何x,y,z,如果x.equal(y)返回true,y.equal(z)返回true,那么z.equal(x)返回true也應(yīng)該返回true。
一致性:如果x,y的引用沒有發(fā)生變化,那么反復(fù)調(diào)用equal方法應(yīng)該返回同樣的結(jié)果
非空性:對于任意非空引用x,x.equal(null)都應(yīng)該返回false
為了滿足實際需要,這個時候我們就需要重寫equal方法,針對規(guī)范,比較典型的寫法如下:
Java代碼
/**
* @author GraMind
* @param obj
* @return
* @exception
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
if (this == obj) 1
return true;
if (obj == null) 2
return false;
if (getClass() != obj.getClass()) 3
return false;
ClassName other = (ClassName) obj; 4
if (id != other.id) 5
return false;

.
return true;
}
* @author GraMind
* @param obj
* @return
* @exception
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
if (this == obj) 1
return true;
if (obj == null) 2
return false;
if (getClass() != obj.getClass()) 3
return false;
ClassName other = (ClassName) obj; 4
if (id != other.id) 5
return false;


return true;
}
對于上面的代碼
1)檢測兩者是否引用同一個對象
2)檢測object是否為null,如果為null直接返回false
3)避免父子類引用相同的域(比如上類父子都具有id屬性),比較是否屬于同一級類,如果每個子類都具有統(tǒng)一的語義也可以使用instanceof來檢測
4)轉(zhuǎn)換要比較的類為對應(yīng)的類類型變量
5)根據(jù)需要比較相應(yīng)的域
注意:如果在子類中重寫了equal方法,就要在其中包含super.equal(...)。
散列碼
散列碼是有對象導(dǎo)出來的一個整形值,且沒有規(guī)律。如果重寫equal方法那么就必須重寫hashCode方法
想要明白為什么這樣做,你必須要先知道Java中的集合。
總的來說,Java中的集合(Collection)有兩類,一類是List,再有一類是Set。
你知道它們的區(qū)別嗎?前者集合內(nèi)的元素是有序的,元素可以重復(fù);后者元素無序,但元素不可重復(fù)。
那么這里就有一個比較嚴重的問題了:要想保證元素不重復(fù),可兩個元素是否重復(fù)應(yīng)該依據(jù)什么來判斷呢?
這就是Object.equals方法了。但是,如果每增加一個元素就檢查一次,那么當元素很多時,后添加到集合中的元素比較的次數(shù)就非常多了。
也就是說,如果集合中現(xiàn)在已經(jīng)有1000個元素,那么第1001個元素加入集合時,它就要調(diào)用1000次equals方法。這顯然會大大降低效率。
于是,Java采用了哈希表的原理。哈希(Hash)實際上是個人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。
哈希算法也稱為散列算法,是將數(shù)據(jù)依特定算法直接指定到一個地址上。
初學(xué)者可以這樣理解,hashCode方法實際上返回的就是對象存儲的物理地址(實際可能并不是,比如大家可以看下String的hashCode實現(xiàn))。
這樣一來,當集合要添加新的元素時,先調(diào)用這個元素的hashCode方法,就一下子能定位到它應(yīng)該放置的物理位置上。
如果這個位置上沒有元素,它就可以直接存儲在這個位置上,不用再進行任何比較了;如果這個位置上已經(jīng)有元素了,
就調(diào)用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址。
所以這里存在一個沖突解決的問題。這樣一來實際調(diào)用equals方法的次數(shù)就大大降低了,幾乎只需要一兩次。
所以,Java對于eqauls方法和hashCode方法是這樣規(guī)定的:
1、如果兩個對象相同,那么它們的hashCode值一定要相同;2、如果兩個對象的hashCode相同,它們并不一定相同 上面說的對象相同指的是用eqauls方法比較。
-----------------------------------------------------
Silence, the way to avoid many problems;
Smile, the way to solve many problems;
posted on 2012-11-03 11:00 Chan Chen 閱讀(293) 評論(0) 編輯 收藏 所屬分類: Scala / Java