光阴似箭催人老,日月如移越少年。
實作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()而不違反約定;
所以真正的問題在於 你如何定義相等。代碼是次要的。
如果定義相等為"經度和緯度分別相等",那麼你給的代碼是一個可以用的方案 (但不是唯一的可用方案)。