j2ee高級開發技術課程第八週

介紹1、java

 

 hashCode()方法和equal()方法的做用其實同樣,在Java裏都是用來對比兩個對象是否相等一致,那麼equal()既然已經能實現對比的功能了,爲何還要hashCode()呢?程序員

由於重寫的equal()裏通常比較的比較全面比較複雜,這樣效率就比較低,而利用hashCode()進行對比,則只要生成一個hash值進行比較就能夠了,效率很高,那麼hashCode()既然效率這麼高爲何還要equal()呢?算法

由於hashCode()並非徹底可靠,有時候不一樣的對象他們生成的hashcode也會同樣(生成hash值得公式可能存在的問題),因此hashCode()只能說是大部分時候可靠,並非絕對可靠,因此咱們能夠得出:數據結構

         1.equal()相等的兩個對象他們的hashCode()確定相等,也就是用equal()對比是絕對可靠的。this

         2.hashCode()相等的兩個對象他們的equal()不必定相等,也就是hashCode()不是絕對可靠的。.net

全部對於須要大量而且快速的對比的話若是都用equal()去作顯然效率過低,因此解決方式是,每當須要對比的時候,首先用hashCode()去對比,若是hashCode()不同,則表示這兩個對象確定不相等(也就是沒必要再用equal()去再對比了),若是hashCode()相同,此時再對比他們的equal(),若是equal()也相同,則表示這兩個對象是真的相同了,這樣既能大大提升了效率也保證了對比的絕對正確性! hibernate

     這種大量的而且快速的對象對比通常使用的hash容器中,好比hashset,hashmap,hashtable等等,好比hashset裏要求對象不能重複,則他內部必然要對添加進去的每一個對象進行對比,而他的對比規則就是像上面說的那樣,先hashCode(),若是hashCode()相同,再用equal()驗證,若是hashCode()都不一樣,則確定不一樣,這樣對比的效率就很高了。code

      然而hashCode()和equal()同樣都是基本類Object裏的方法,而和equal()同樣,Object裏hashCode()裏面只是返回當前對象的地址,若是是這樣的話,那麼咱們相同的一個類,new兩個對象,因爲他們在內存裏的地址不一樣,則他們的hashCode()不一樣,因此這顯然不是咱們想要的,因此咱們必須重寫咱們類的hashCode()方法,即一個類,在hashCode()裏面返回惟一的一個hash值,好比下面:對象

自定義一個類 內存

class Person{

   int num;

   String name;

 

   public int hashCode(){

      return num*name.hashCode();

}

因爲標識這個類的是他的內部的變量num和name,因此咱們就根據他們返回一個hash值,做爲這個類的惟一hash值。 

因此若是咱們的對象要想放進hashSet,而且發揮hashSet的特性(即不包含同樣的對象),則咱們就要重寫咱們類的hashCode()和

equal()方法了。像String,Integer等這種類內部都已經重寫了這兩個方法。

 

固然若是咱們只是平時想對比兩個對象 是否一致,則只重寫一個equal(),而後利用equal()去對比也行的。

 

介紹2、

哈希碼(HashCode)

哈希碼產生的依據:哈希碼並非徹底惟一的,它是一種算法,讓同一個類的對象按照本身不一樣的特徵儘可能的有不一樣的哈希碼,但不表示不一樣的對象哈希碼徹底不一樣。也有相同的狀況,看程序員如何寫哈希碼的算法。

 

什麼是哈希碼(HashCode)

在Java中,哈希碼錶明對象的特徵。
例如對象 String str1 = 「aa」, str1.hashCode= 3104
String str2 = 「bb」, str2.hashCode= 3106
String str3 = 「aa」, str3.hashCode= 3104
根據HashCode由此可得出str1!=str2,str1==str3
下面給出幾個經常使用的哈希碼的算法。
1:Object類的hashCode.返回對象的內存地址通過處理後的結構,因爲每一個對象的內存地址都不同,因此哈希碼也不同。
2:String類的hashCode.根據String類包含的字符串的內容,根據一種特殊算法返回哈希碼,只要字符串所在的堆空間相同,返回的哈希碼也相同。
3:Integer類,返回的哈希碼就是Integer對象裏所包含的那個整數的數值,例如Integer i1=new Integer(100),i1.hashCode的值就是100 。因而可知,2個同樣大小的Integer對象,返回的哈希碼也同樣。

equals方法在hibernate中的應用。

equals方法是默認的判斷2個對象是否相等的方法,在Object類裏有實現,判斷的是2個對象的內存地址。在hibernate中,不容許存在同類對象中有2個同樣的實例。hibernate經過equals方法作判斷。如:
User u1 = new User(「張三」);
User u2 = new User(「李四」);
User u3 = new User(「張三」);
按照項目需求,用戶只要名字相同,就表示同一個用戶,因此咱們認爲,u1和u3是同一我的,同一個對象。可是由於u1,u2,u3三者的內存地址都各不相同,因此hibernate會認爲這是3個不一樣的對象。這與咱們假設的出了矛盾。 所以,咱們將覆蓋Object類中的equals方法。
public class User{
private String userName;
….//get ,set方法省
//覆蓋Object裏的equals方法
public boolean equals(Object arg0){
if (!(arg0 instanceof User)){
return false;
}
User user = (User)arg0;
//若是名字相同,則表示屬於同一個對象。
if(user.getName().equals(this.getName)){
return true;
}else{
return false; }
}
這樣hibernate在插入數據的時候,若是傳過來一個叫」張三」的用戶,hibernate會先判斷有沒有叫「張三」的用戶,若是沒有,就容許插入,若是有,就不容許插入。這樣作能夠保證數據的高度一致性,不一樣的項目有不一樣的需求,因此要根據本身的需求來覆蓋equals方法。

equals和HashCode的關係

在hibernate中,它認爲2個對象只要equals返回true,那麼hashCode必定相等。 可是實際狀況呢?
User u1 = new User(「張三」);
User u2 = new User(「張三」);
因爲咱們重寫了User的equals方法,因此 u1.equals(u2);返回true 可是,User並無重寫hashCode方法,它用的是Object類的hashCode方法,因此 u1.hashCode = 31050006 u2.hashCode = 31587890 二者的hashCode並不相等。違背了hibernate的原則 由此hibernate會產生錯誤判斷,又覺得它們不是同一個對象,所以咱們還得重寫User 的hashCode方法。如何重寫hashCode方法呢?

HashCode的重寫

如第2節所講,哈希碼要完成這麼一件事,首先要保證若是equlas出來的結果相等,那麼hashCode也相等。像上面的u1和u2,因爲名字都是「張三」,因此應該返回相同的hashCode。因此咱們能夠想一個辦法。讓User的哈希碼返回User裏面name字段的哈希碼,這樣就保證,名字相同的人,不但equlas方法相同,並且hashCode相等。 那麼User類就變成
public class User{
private String userName;
//覆蓋Object裏的equals方法
public boolean equals(Object arg0){
if(!(arg0 instanceof User)){
return false;
}
User user = (User)arg0;
//若是名字相同,則表示屬於同一個對象。
if (user.getName().equals(this.getName)){
return true;
}else{
return false;
}
}
//覆蓋Object裏的hashCode方法
public int hashCode() {
return name.hashCode();//返回名字的哈希碼。
}
}
這樣能夠保證hibernate根據咱們本身的需求來判斷重複對象
相關文章
相關標籤/搜索