哈希冲突
1.开放定址法
2.再哈希法
3.链地址法(JAVA官方,默认使用单向链表将元素串起来,在添加元素时,可能会由单向链表转为红黑树来存储元素,比如当哈希表容量>=64且单向链表的节点数量大于8时JDK1.8)
哈希函数
1.先生成key的哈希值(整数)
2.再让key的hash值跟数组的大小进行运算(和数组长度进行取模),生成一个索引值
hash_code(key)%table.length
为了提高效率,可以使用&位运算取代%运算【前提:将数组的长度设计为2^n】
hash_code(key)&(table.length-1) (2^n-1)转二进制全都是1,进行与运算后得到0-(table.length-1)
如何生成key的hash值
整数的hash值是自己
浮点数的hash值是在计算机中存储的二进制数据(Java:int code = Float.floatToIntBits(10.6f))
long类型(JAVA官方hashcode是返回Int32位类型,long是64位,需要进行运算
(int)(value ^ (value >>> 32)));
double类型(JAVA官方:long bits = doubleToLongBits(value); (int)(bits ^ (bits >>> 32)))
字符串类型:
jack = ((j*31+a)*31+c)*31+k
31是一个奇素数,JVM会将31*i优化成(i<<5)-i
扩容:
装填因子:节点总数量/哈希表桶数组长度,也叫做负载因子
在JDK1.8中的hashmap中,如果装填因子超过0.75,就扩容为原来的2倍