API文檔中HashCode和equals方法定義java
public int hashCode()程序員 |
返回該對象的哈希碼值。支持此方法是爲了提升哈希表性能。hashCode的常規協定是編程
|
public boolean equals()數組 |
指示其餘某個對象是否與此對象「相等」。equals 方法在非空對象引用上實現相等關係:編程語言
|
當一個類有本身特有的「邏輯相等」概念(不一樣於對象身份的概念)時,須要重寫equals方法性能
【1】.使用instanceof操做符檢查「實參是否爲正確的類型」。優化
【2】.對於類中的每個「關鍵域」,檢查實參中的域與當前對象中對應的閾值。this
【2.1】對於非float和double類型的原語類型域,使用==比較spa
【2.2】對於對象引用域,遞歸調用equals方法設計
【2.3】對於float域,使用Float.floatToIntBits(afloat)轉化爲int,再使用==比較。
【2.4】對於數組域,調用Arrays.equals方法.
【1】.把某個非零常數值,保存在int變量result中
【2】.對於對象中每個關鍵域f(指equals方法中考慮的每個域):
【2.1】boolean型,計算(f?0:1)
【2.2】byte,char,short型,計算(int)
【2.3】long型,計算(int)(f ^(f >>>32))
【2.4】float型,計算Float.floatToIntBits(afloat)
【2.5】double型,計算Double.doubleToLongBits(abouble)獲得一個long,再執行[2.3]
【2.6】對象引用,遞歸調用它的hashCode方法
【2.7】數組域,對其中每一個元素調用它的hashCode方法
【3】.將上面計算獲得的散列碼保存到int變量c中,而後執行result=37*result +c;
【4】.返回result
在Object類中定義的hashCode方法代碼以下:
public native int hashCode();
這說明hashCode()本地機器相關的方法。jre6中String實現hashCode()的代碼以下:
/** * Returns a hash code for this string. The hash code for a * {@code String} object is computed as * <blockquote><pre> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * </pre></blockquote> * using {@code int} arithmetic, where {@code s[i]} is the * <i>i</i>th character of the string, {@code n} is the length of * the string, and {@code ^} indicates exponentiation. * (The hash value of the empty string is zero.) * * @return a hash code value for this object. */ public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
String實現hashCode()方法中利用了公式s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]。對這公式的解讀:
s[i]是string的第i個字符,n是String的長度。31爲啥呢?之因此選擇31,是由於它是個奇素數,若是乘數是偶數,而且乘法溢出的話,信息就會丟失,由於與2相乘等價於移位運算。使用素數的好處並非很明顯,可是習慣上都使用素數來計算散列結果。31有個很好的特性,就是用移位和減法來代替乘法,能夠獲得更好的性能:31*i==(i<<5)-i。如今的VM能夠自動完成這種優化。