哈希碼

哈希碼

哈希碼產生的依據:哈希碼並不是完全唯一的,它是一種演演算法,讓同一個類的對象按照自己不同的特徵盡量的有不同的哈希碼,但不表示不同的對象哈希碼完全不同。也有相同的情況,看程序員如何寫哈希碼的演演算法。在Java中,哈希碼代表對象的特徵。

簡介


哈希碼
哈希碼
什麼是哈希碼(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方法。
判斷方法編輯
為什麼不按主鍵來判斷
因為主鍵是在插入數據進資料庫之後才產生的,在一個對象還沒有被持久化的時候,它是沒有主鍵的,所以hibernate無法根據主鍵判斷它是否有相同數據。

兩者關係


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