84669 人學習
152542 人學習
20005 人學習
5487 人學習
7821 人學習
359900 人學習
3350 人學習
180660 人學習
48569 人學習
18603 人學習
40936 人學習
1549 人學習
1183 人學習
32909 人學習
光阴似箭催人老,日月如移越少年。
實作hashCode方法的通用約定
hashCode
在應用程式的執行期間,只要物件的equals方法的比較操作所用到的資訊沒有被修改,那麼對這個同一物件呼叫多次,equals方法的比较操作所用到的信息没有被修改,那么对这个同一对象调用多次,hashCode方法必須一致地傳回同一個整數。在同一個應用程式的多次執行過程中,每次執行所傳回的整數可以不一致。 如果兩個物件根據equals(Object)方法比較是相等的,那麼呼叫這兩個物件中任意一個物件的equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。反之,如果两个对象hashCode方法返回整数结果一样,则不代表两个对象相等,因为equals方法都必須產生同樣的整數結果。反之,如果兩個物件方法傳回整數結果一樣,則不代表兩個物件相等,因為equals方法可以被重載。 equals(Object)方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode如果兩個物件根據equals(Object)方法比較是不相等的,那麼呼叫這兩個物件中任意一個物件的方法,則不一定要產生不同的整數結果。但,如果能讓不同的物件產生不同的整數結果,則有可能提高散列表的效能。
在應用程式的執行期間,只要物件的equals方法的比較操作所用到的資訊沒有被修改,那麼對這個同一物件呼叫多次,equals方法的比较操作所用到的信息没有被修改,那么对这个同一对象调用多次,hashCode方法必須一致地傳回同一個整數。在同一個應用程式的多次執行過程中,每次執行所傳回的整數可以不一致。
equals
如果兩個物件根據equals(Object)方法比較是相等的,那麼呼叫這兩個物件中任意一個物件的equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。反之,如果两个对象hashCode方法返回整数结果一样,则不代表两个对象相等,因为equals方法都必須產生同樣的整數結果
equals(Object)
equals(Object)方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode
散列碼計算(來自:Effective Java) 17,保存在一个名为result的int把某個非零的常數值,例如類型的變數中。 f(指equals 對於物件中每個關鍵域方法中涉及的每個域),完成以下步驟: int 為該域計算類型的雜湊碼c: boolean类型,则计算(f?1:0如果該域是)。 byte,char,short或者int类型,则计算(int)f如果該域是。 long类型,则计算(int)(f^(f>>>32))如果該域是。 float类型,则计算Float.floatToIntBits(f)如果該域是。 double类型,则计算Double.doubleToLongBits(f),然后按照步骤2.1.3,为得到的long如果該域是double類型,則計算Double.doubleToLongBits(f),然後按照步驟2.1.3 ,為得到的long 類型值計算雜湊值。 equals方法通过递归地调用equals的方式来比较这个域,则同样为这个域递归地调用hashCode。如果需要更复杂的比较,则为这个域计算一个范式(canonical representation),然后针对这个范式调用hashCode。如果这个域的值为null,则返回0如果該域是一個物件引用,並且該類別的equals方法透過遞歸地呼叫equals的方式來比較這個域,則同樣為這個域遞歸地調用🎜。如果需要更複雜的比較,則為這個域計算一個範式(canonical representation),然後針對這個範式呼叫🎜。如果這個網域的值為null,則傳回0(其他常數也行)。 🎜 如果該域是一個數組,則要把每一個元素當作單獨的域來處理。也就是說,遞歸地應用上述規則,對每個重要的元素計算一個雜湊碼,然後根據步驟2.2中的做法把這些雜湊值組合起來。如果數組域中的每個元素都很重要,可以利用發行版本1.5中增加的其中一個Arrays.hashCode方法。 按照下面的公式,把步驟2.1中計算得到的散列碼c合并到result中:result = 31 * result + c; //此处31是個奇素數,並且有個很好的特性,即用移位和減法來代替乘法,可以得到更好的性能:`31* i == (i 回傳result 檢驗並測試該hashCode實作是否符合通用約定。
17,保存在一个名为result的int
17
result
int
f(指equals 對於物件中每個關鍵域
f
boolean类型,则计算(f?1:0
boolean
f?1:0
byte,char,short或者int类型,则计算(int)f
byte
char
short
(int)f
long类型,则计算(int)(f^(f>>>32))
long
(int)(f^(f>>>32))
float类型,则计算Float.floatToIntBits(f)
float
Float.floatToIntBits(f)
double类型,则计算Double.doubleToLongBits(f),然后按照步骤2.1.3,为得到的long
double
Double.doubleToLongBits(f)
equals方法通过递归地调用equals的方式来比较这个域,则同样为这个域递归地调用hashCode。如果需要更复杂的比较,则为这个域计算一个范式(canonical representation),然后针对这个范式调用hashCode。如果这个域的值为null,则返回0
(canonical representation)
null
0
如果該域是一個數組,則要把每一個元素當作單獨的域來處理。也就是說,遞歸地應用上述規則,對每個重要的元素計算一個雜湊碼,然後根據步驟2.2中的做法把這些雜湊值組合起來。如果數組域中的每個元素都很重要,可以利用發行版本1.5中增加的其中一個Arrays.hashCode方法。
Arrays.hashCode
按照下面的公式,把步驟2.1中計算得到的散列碼c合并到result中:result = 31 * result + c; //此处31是個奇素數,並且有個很好的特性,即用移位和減法來代替乘法,可以得到更好的性能:`31* i == (i
c
result = 31 * result + c
31
回傳result
檢驗並測試該hashCode實作是否符合通用約定。
範例實作
@Override public int hashCode() { int result = 17; result = 31 * result + (origin == null ? 0 : origin.hashCode()); result = 31 * result + (hsNumber == null ? 0 : hsNumber.hashCode()); result = 31 * result + (imageUrl == null ? 0 : imageUrl.hashCode()); result = 31 * result + (classificationName == null ? 0 : classificationName.hashCode()); return result; }
java的int固定為32位元。另外你的latitude和longtitude是double..我覺得會是64位。
hashcode 和equals 這兩個方法是有約定的語意的,你可以看一下 Object
你寫的那個equals我覺得可以用。
注意: Object類別中的約定其實是個很弱的約束。我們可以寫出這樣的hashcode()和equals()而不違反約定;
public int hashcode() { return 0; } public boolean equals(Object o) { return (o != null) && (o.getClass() == getClass()); }
所以真正的問題在於 你如何定義相等。代碼是次要的。 如果定義相等為"經度和緯度分別相等",那麼你給的代碼是一個可以用的方案 (但不是唯一的可用方案)。
實作
hashCode
方法的通用約定hashCode
範例實作
java的int固定為32位元。另外你的latitude和longtitude是double..我覺得會是64位。
hashcode 和equals 這兩個方法是有約定的語意的,你可以看一下 Object
你寫的那個equals我覺得可以用。
注意: Object類別中的約定其實是個很弱的約束。我們可以寫出這樣的hashcode()和equals()而不違反約定;
所以真正的問題在於 你如何定義相等。代碼是次要的。
如果定義相等為"經度和緯度分別相等",那麼你給的代碼是一個可以用的方案 (但不是唯一的可用方案)。