写在前面
Two sum引起的学习。
- 暴力解决中发现忘记了如何创建数组
- 查看解决方案,产生了HashMap怎么做到O(1)的疑问
特别感谢:“淡腾的枫”的《HashMap中的hash函数》
创建一个int数组
int[] arr = new int[5];
int[] arr = {};
HashMap
&,|,~,^,>>>
Object.hashCode
Object的hashCode方法
public native int hashCode();
通过阅读方法上的注释,理解了hashCode()的稳定反馈效果即可。
hash函数
这段代码叫**“扰动函数”**
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
重拾二进制
Object的hashCode()方法返回一个int值。
2进制32位带符号的int类型,能表达的数值范围 -231 ~ 231-1
(h = key.hashCode()) ^ (h >>> 16)
hashCode返回一个32位码,将它与右移16位之后的码做异或
-
右移:高位补0(无论正负),也就是把数字向右推,h的高16位,就是h >>> 16的低16位。
-
这样异或的结果,在其低16位中,h的高位和低位都得以体现。
hash函数的用途
举例,HashMap的getNode中, tab[(n - 1) & hash]
(为什么不直接用hash值作为数组下标:hash值是32位bit,数值范围巨大,内存是不能存下这么大的数组的)
n 是集合大小,hash是hash()的结果。
集合大小是2的整数幂。
2的整数幂表达为2进制,如
22 ==> 100
23 ==> 1000
24 ==> 10000
这些数值-1之后,得到了“低位掩码”,如11,111,1111
这样的码和hash值做与操作时,hash的低几位作为了Node数组的下标