写在前头
这篇文章要从翻看Android4.2源码时发现一个牛气哄哄的注释开始,就是下边这块:
// Doug Lea's supplemental secondaryHash function (inlined)
int hash = key.hashCode();
hash ^= (hash >>> 20) ^ (hash >>> 12);
hash ^= (hash >>> 7) ^ (hash >>> 4);
先不管这段代码写的是啥,先看看这段注释:Doug Lea's supplemental secondaryHash function (inlined)
Doug Lea's,这是个人名,说的就是下边这个牛逼轰轰的人:
supplemental这个单词得查一下。意思是:补充的
secondaryHash这个单词得会,记住要考。百度搜索结果就是下边这几个字:
这个注释翻译一下就是:道格·利的扩展二级哈希方法.
正文
再仔细看看这段方法,进行了一顿位操作。
我们经常使用>> 但是>>>是啥意思?多了一个“>”,啥意思?一脸懵逼...
借此机会复习一下这两个位操作有啥区别,其实这两个符号只有一个区别,就是作用不同。
">>"是带符号右移动啥叫带符号右移?如果该数为正,则高位补0,若为负数,则高位补1。如:int i=18; i>>2的结果是4,移出的部分将被抛弃。
“>>>"表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0。
然而^操作又是干啥的?
^官方名字叫异或运算,逻辑含义是无符号整形加法操作。
妥了,开始进入正题了。这段这段代码是干嘛的?
// Doug Lea's supplemental secondaryHash function (inlined)
int hash = key.hashCode();
hash ^= (hash >>> 20) ^ (hash >>> 12);
hash ^= (hash >>> 7) ^ (hash >>> 4);
- 先对key做hashcode,那么什么叫hashcode。hashcode广义的理解就是把任意长度的输入通过散列算法变换成固定长度的输出,该输出值就是hashcode。java中对hashcode生成规则有很多种,这里不做解释,感兴趣的可以查查资料。
- 做了一堆位操作。目的就是java原生生成的散列更加更加均匀,感兴趣的话可以琢磨一下这几个操作的意义。稍微解释一下什么叫均匀?一个十进制数32768(二进制1000 0000 0000 0000)、经过上述公式运算之后的结果是35080(二进制1000 1001 0000 1000)看出来了吗?或许这样还看不出什么。再举个数字61440(二进制1111 0000 0000 0000)、运算结果是65263(二进制1111 1110 1110 1111)现在应该很明显了、它的目的是让“1”变的均匀一点、散列的本意就是要尽量均匀分布。
PS
OK,我们回过头来重新来看这段代码,感叹Java源码中到处散播着博大精深的实现以及细节。
笔者翻看了最新的Android源码以及Java1.8源码发现这段代码实际已经不存在了。但是实现思路大同小异。感兴趣的同学看看。