HashCode 意義:
總的來說,Java中的集合(Collection)有兩類,一類是List,再有一類是Set。你知道它們的區別嗎?前者集合內的元素是有序的,元素可以重復;后者元素無序,但元素不可重復。那么這里就有一個比較嚴重的問題了:要想保證元素不重復,可兩個元素是否重復應該依據什么來判斷呢?這就是 Object.equals方法了。但是,如果每增加一個元素就檢查一次,那么當元素很多時,后添加到集合中的元素比較的次數就非常多了。也就是說,如果集合中現在已經有1000個元素,那么第1001個元素加入集合時,它就要調用1000次equals方法。這顯然會大大降低效率。
於是,Java采用了哈希表的原理。哈希算法也稱為散列算法,是將數據依特定算法直接指定到一個地址上。關於哈希算法,這里就不詳細介紹。可以這樣簡單理解,hashCode方法實際上返回的就是對象存儲位置的映像。
這樣一來,當集合要添加新的元素時,先調用這個元素的hashCode方法,就能定位到它應該放置的存儲位置。如果這個位置上沒有元素,它就可以直接存儲在這個位置上,不用再進行任何比較了;如果這個位置上已經有元素了,就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就表示發生沖突了,散列表對於沖突有具體的解決辦法,但最終還會將新元素保存在適當的位置。這樣一來,實際調用equals方法的次數就大大降低了,幾乎只需要一兩次。
原則:
在編寫類的時候,如果覆蓋了Object的equals方法,那么必須要覆蓋hashCode方法,並且如果兩個對象用equals方法比較返回true,那么這兩個對象hashCode返回的值也必須是相等的,並且對於同一個對象,equals方法需要比較的屬性值沒有被修改,那么每次調用hashCode返回的值應該是一致的。
重寫:
1
2
3
4
5
6
7
8
9
10
11
12
|
public
static
int
hashCode(
long
a[]) {
if
(a ==
null
)
return
0
;
int
result =
1
;
for
(
long
element : a) {
int
elementHash = (
int
)(element ^ (element >>>
32
));
result =
31
* result + elementHash;
}
return
result;
}
|
例子:
String.hashCode();
public int hashCode() { int hash = hashCode; if (hash == 0) { if (count == 0) { return 0; } final int end = count + offset; final char[] chars = value; for (int i = offset; i < end; ++i) { hash = 31*hash + chars[i]; } hashCode = hash; } return hash; }
問題:
hashcode 通過什么散列算法實現的。
怎么解釋以上的hash算法,為什么要*31,為什么要》》》31 等。
部分參考資料:
http://my.oschina.net/chihz/blog/56256