HashMap在jdk1.7和jdk1.8的区别
- 底层结构:在1.7采用数组+链表,在1.8采用数组+链表+红黑树
- 初始化方式:1.7采用inflateTable()初始化数组;1.8采用resize()扩容
- put实现方式:1.7采用头插法,1.8采用尾插法
- hash实现方式:1.7直接计算key的hashcode值;1.8采用==(key的hashcode值)异或(key的hashcode值无符号右移16位)的结果==
- 扩容策略:在1.7的时候,只要元素个数不小于阈值(加载因子0.75)直接扩容2倍。在1.8的时候,单链表元素超过8个,将单链表转换成红黑树,若红黑树结点小于6个,将红黑树转换成单链表。
Hash冲突及其解决
hash冲突:key通过hash函数得到的结果作为地址存储键值对,当计算发现这个地址已经存储了键值对,这就发生了hash冲突。
1、开放定址法:一旦产生了冲突,就按某种规则去寻找另一空地址,若发生了第 i 次冲突,试探的下一个地址将增加di,基本公式是:
线性探测:di = i
平方探测:di = ± i2( +12, -12, +22, -22……)
双散列:di = i * h2(key)
2、再哈希法:对冲突的hash值再进行哈希处理
3、链地址法:将产生冲突的元素放在一个单链表上
4、建立公共溢出区:将哈希表分为基本表和溢出表两部分,凡是和基本表产生冲突的元素都放入溢出表
HashMap原理
- 数组每一个元素都是单链表
- 加载因子0.75,即容量使用3/4就开始扩容
- 不可重复
- 无序,因为不知道值挂到哪个单链表了