刷題的時(shí)候,用了java的hashset粉洼,泛型里面用了int[], 但是總是remove不成功,debug了下發(fā)現(xiàn)hash不成功茵瘾,查了下源代碼,貌似泛型里面只能用object栖秕。剛開始以為可能hash的是object的地址弧岳,但是想起來(lái)唬涧,如果是gc了轉(zhuǎn)移新生代老生代的話譬正,那么hash不就沒(méi)用了么宫补。決定去深扒下代碼。
set采用的和hashmap一樣的方法曾我,hashmap的源代碼是這樣的:
static final int hash(Object key) {
????int h;
? ? return (key ==null) ?0 : (h = key.hashCode()) ^ (h >>>16);
}
理論上如果直接用32位的int值粉怕,從-2147483648到2147483648,40多億的數(shù)組抒巢,如果不是跑大數(shù)據(jù)的話斋荞,應(yīng)該平時(shí)也就夠了。但內(nèi)存不夠虐秦,如果只取后幾位的話,概率分布不好的話凤优,很可能出現(xiàn)一個(gè)桶已經(jīng)滿了悦陋,剩下的空著的情況,因此java采取了高半?yún)^(qū)和低半?yún)^(qū)做異或筑辨。那么h又是怎么來(lái)的呢俺驶,hashcode是如何實(shí)現(xiàn)的?
繼續(xù)扒代碼棍辕,發(fā)現(xiàn)是native暮现,放棄,下載openjdk開扒楚昭。
這是c里面的:
JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
? JVMWrapper("JVM_IHashCode");
? // as implemented in the classic virtual machine; return 0 if object is NULL
? returnhandle ==NULL?0: ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ;
JVM_END
FastHashCode一百多行就不貼了
看了半天栖袋,發(fā)現(xiàn),hashcode并不是基于地址做的hash抚太,至少openjdk8不是塘幅,而是基于thread state,只hash一次尿贫,緩存存到object header的mark word里面电媳,還有什么biasblock沒(méi)看懂==
google一番,搜到了別人寫的才明白:
https://srvaroa.github.io/jvm/java/openjdk/biased-locking/2017/01/30/hashCode.html