哈希碼

1、什麼是哈希碼(HashCode)

在Java中,哈希碼代表對象的特徵。例如對象

String str1 = “aa”, str1.hashCode= 3104
String str2 = “bb”, str1.hashCode= 3106
String str3 = “aa”, str1.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對象,返回的哈希碼也一樣。

2、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個不同的對象。這與我們假設的出了矛盾。

因此,我們將覆蓋User的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會先判斷有沒有叫“張三”的用戶,如果沒有,就允許插入,如果有,就不允許插入。這樣做可以保證數據的高度一致性,不同的項目有不同的需求,所以要根據自己的需求來覆蓋equlas方法。

3、爲什麼不按主鍵來判斷
因爲主鍵是在插入數據進數據庫之後才產生的,在一個對象還沒有被持久化的時候,它是沒有主鍵的,所以hibernate無法根據主鍵判斷它是否有相同數據。

equlas和HashCode的關係。

在hibernate中,它認爲2個對象只要equlas返回true,那麼hashCode一定相等。

但是實際情況呢?
User u1 = new User(“張三”);
User u2 = new User(“張三”);

由於我們重寫了User的equlas方法,所以
u1.equlas(u2);返回true 
但是,User並沒有重寫hashCode方法,它用的是Object類的hashCode方法,所以
u1.hashCode = 31050006
u2.hashCode = 31587890
兩者的hashCode並不相等。違背了hibernate的原則

由此hibernate會產生錯誤判斷,又以爲它們不是同一個對象,因此我們還得重寫User
的hashCode方法。如何重寫hashCode方法呢?

4、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根據我們自己的需求來判斷重複對象

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章