-
哈希碼
鎖定
哈希碼(HashCode),並不是完全唯一的,它是一種算法,讓同一個類的對象按照自己不同的特徵儘量的有不同的哈希碼,但不表示不同的對象哈希碼完全不同。也有相同的情況,看程序員如何寫哈希碼的算法。
- 中文名
- 哈希碼
- 外文名
- HashCode
- 類 別
- 一種算法
- 包 括
- equals和HashCode
- 應 用
- java編程
- 應用代碼類別
- Object類,String類,Integer類
哈希碼簡介
在Java中,哈希碼代表對象的特徵。
例如對象 String str1 = “aa”, str1.hashCode= 3104
String str2 = “bb”, str2.hashCode= 3106
String str3 = “aa”, str3.hashCode= 3104
根據HashCode由此可得出str1!=str2,str1==str3
下面給出幾個常用的哈希碼的算法。
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的重寫
哈希碼要完成這麼一件事,首先要保證如果equals出來的結果相等,那麼hashCode也相等。像上面的u1和u2,由於名字都是“張三”,所以應該返回相同的hashCode。所以我們可以想一個辦法。讓User的
[2]
哈希碼返回User裏面name字段的哈希碼,這樣就保證,名字相同的人,不但equals方法相同,而且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根據我們自己的需求來判斷重複對象
- 參考資料
-
- 1. 內存地址泄漏分析與防禦 .知網[引用日期2017-04-06]
- 2. 面向多示例數據檢索的哈希方法研究 .知網[引用日期2017-04-06]