Object.hashCode()与Object.equals()
【README】
本文旨在po出 hashCode , equals的api描述,以加深理解;
本文翻譯自 jdk 文檔;
【1】Object.hashCode()
1)介紹:返回對象的哈希碼值。支持此方法是為了有利于哈希表,例如由 java.util.HashMap 提供的哈希表。
在 Java 應用程序執行期間,只要在同一個對象上多次調用它,hashCode 方法必須始終返回相同的整數,前提是對象上的 equals 比較中使用的信息沒有被修改。該整數不需要從應用程序的一次執行到同一應用程序的另一次執行保持一致。
hashCode方法需要遵守的約定:如果根據 equals(Object) 方法兩個對象相等,則對兩個對象中的每一個調用 hashCode 方法必須產生相同的整數結果(*干貨)。
如果根據 equals(Object) 方法兩個對象不相等,則不需要對這兩個對象中的每一個調用 hashCode 方法必須產生不同的整數結果。但是,程序員應該意識到為不相等的對象生成不同的整數結果可能會提高哈希表的性能。
盡可能實用,類 Object 定義的 hashCode 方法確實為不同的對象返回不同的整數。 (這通常通過將對象的內部地址轉換為整數來實現,但 Java? 編程語言不需要這種實現技術。)
補充: 可以看下 equals(), System.identityHashCode()
【1.1】String.hashCode()
返回此字符串的哈希碼。 String 對象的哈希碼計算如下
??????? s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]? ?????
使用 int 算術,其中 s[i] 是字符串的第 i 個字符,n 是字符串的長度,^ 表示求冪。 (空字符串的哈希值為零。)
返回:此對象的哈希碼值。
字符串底層是字符數組存儲的,以字符串 aaa為例,存儲結構為 ['a', 'a', 'a'] ,字符a的 ASCII 為97,則hash值計算步驟如下:
i 取值 0, 1, 2;初始時, h=hash=0;
| i | val[i] | h |
| 0 | 97 | 97 |
| 1 | 97 | 31*97+97 => 3104 |
| 2 | 97 | 31*3104+97=> 96321???? |
所以字符串 aaa的hash值等于? 96321 。
我們令 vi = val[i],則以后如下規則:
h0 = v0;
h1=31*v0+v1;
h2=31* [31*v0 + v1] + v2;
...
通過歸納法,我們可以得出字符串的hash值的計算公式為:
hn = 31^n * v0 + 31^n-1 * v1 + ...... + 31 * vn-1 + 31^0 * vn;? 其中,vn表示字符串的第n個字符,n從0開始;
所以 字符串 "aaa" 的hash值 h2 = 31^2 * 97 + 31 * 97 + 97 = 96321 ;
【2】Object.equals ()
1)介紹:指示其他某個對象是否“等于”這個對象。
2)equals 方法在非空對象引用上實現等價關系:
- 它是自反的:對于任何非空引用值 x,x.equals(x) 應該返回 true。
- 它是對稱的:對于任何非空引用值 x 和 y,當且僅當 y.equals(x) 返回 true 時,x.equals(y) 才應返回 true。
- 它是可傳遞的:對于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true 并且 y.equals(z) 返回 true,那么 x.equals(z) 應該返回 true。
- 它是一致的:對于任何非空引用值 x 和 y,x.equals(y) 的多次調用始終返回 true 或始終返回 false,前提是對象的 equals 比較中使用的信息沒有被修改。
對于任何非空引用值 x,x.equals(null) 應返回 false。
Object 類的 equals 方法實現了對象上最有區別的可能等價關系;也就是說,對于任何非空引用值 x 和 y,當且僅當 x 和 y 引用同一個對象(x == y 的值為 true)時,此方法才返回 true。
請注意,每當重寫此方法時,通常都需要重寫 hashCode 方法,以維護 hashCode 方法的一般約定,即相等的對象必須具有相等的哈希碼。
補充:也可以看看: hashCode(), java.util.HashMap
【3】System.identityHashCode(Object x)
1)介紹:為給定對象返回與默認方法 hashCode() 返回的相同的哈希碼,無論給定對象的類是否覆蓋 hashCode()。 空引用的哈希碼為零。
【4】HashMap.hash(Object key)?
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}計算 key.hashCode() 并將散列的較高位(異或)傳播到較低位。
由于該表使用二次冪掩碼,因此僅在當前掩碼之上位變化的散列集將始終發生沖突。 (眾所周知的例子是在小表中保存連續整數的浮點鍵集。)
因此,我們應用了一種將較高位的影響向下傳播的變換。 位擴展的速度、效用和質量之間存在權衡。 因為許多常見的哈希集已經合理分布(因此不會從傳播中受益),并且因為我們使用樹來處理 bin 中的大量沖突,所以我們只是以最便宜的方式對一些移位的位進行異或以減少系統損失, 以及合并最高位的影響,否則由于表邊界而永遠不會在索引計算中使用。
總結
以上是生活随笔為你收集整理的Object.hashCode()与Object.equals()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nginx学习小结
- 下一篇: (转)如何保障微服务架构下的数据一致性?