1. HashMap 的实现原理
hashMap使用了三种数据结构,数组,链表和红黑树;
在插入数据时,先获取该数据的hash值两次扰动后存入数组中,如果不重复直接存入,否则形成链表如果链表长度大于8则进化成红黑树;
2. HashMap在JDK1.7和JDK1.8中有哪些不同
1.数据结构发生变化:增加了红黑树;
2.扰动函数发生变化:9次扰动变2次扰动;
3.扩容发生变化;1.8不需要重新计算hash值;
3. 哈希冲突
当两个不同的输入值,根据同一散列函数计算出相同的散列值的现象,我们就把它叫做碰撞(哈希碰撞)。
hashMap使用了两次扰动来降低冲突的频率,一旦冲突则使用链表或者红黑树来解决冲突;
4. 扩容
1.7计算hash值重新分配;1.8不需要hash分配;
另外:第一次扩容发生在table为空的情况;其他发生在size>map容量*负载因子;
指定容量大小后并不一定是你所执行的大小:而是向上 取 2的N次方的 例如 500 的实际大小为 512
代码:
package map的扩容次数;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
HashMap<Object, Object> map = new HashMap<>(500);
Field threshold = map.getClass().getDeclaredField("threshold");
Field size = map.getClass().getDeclaredField("size");
Method capacity = map.getClass().getDeclaredMethod("capacity");
threshold.setAccessible(true);
size.setAccessible(true);
capacity.setAccessible(true);
// 未存放对象时,各项值测试
System.out.println("start:临界值" + threshold.get(map));
System.out.println("start:size" + size.get(map));
System.out.println("start:容量" + capacity.invoke(map))
}
运行结果:
5 put的具体流程
table是map存储数据的数组;resize()是扩容方法;