Java集合-HashMap

143 阅读2分钟

HashMap的底层数据结构:数组和链表

HashMap的存取原理:

存:用key计算hash值来确定数组的插入位置,如果两个key的hash值一样,就按顺序挂在同一个数组位置上,形成链表。
取:1.通过hashcode找到数组的某一元素;2.通过keyequals方法找到链表中的值key对应的值

HashMap的扩容方式?负载因子是多少?为什么是这个值?

resize的触发条件=capacity*load factor,已有数据的容量达到了初始容量的 75%
resize方式:1.创建一个Entry空数组,长度是原来的2倍;2.遍历原数组,把所有的Entry重新hash到新数组,至于为什么要重新hash新数组:index的位置是(hash值&(length-1)),也就是和长度相关的
负载因子:DEFAULT_LOAD_FACTOR 默认0.75,负载因子表示哈希表空间元素密度,越大表示哈希表越满,产生冲突的可能性越大

Java7和Java8的区别

Java7 头插法在多线程操作HashMap时,修改了引用顺序,会引起死循环
Java8 尾插法 不会改变引用顺序,不会导致死循环

为什么会线程不安全

线程安全的替代类

Collections.synchronizedMap(Map):创建安全集合,内部实现就是给方法上锁,加上sychronized关键字
HashTable
ConcurrentHashMap

默认初始化大小?为什么是这个值?为什么大小都是2的幂数?

默认初始化大小是16,2的幂数主要是为了方便位运算

HashMap的主要参数?

最大1<<30 = 2^30
默认初始化容量 1<<4 = 16
负载因子 0.75

HashMap怎么处理hash碰撞?

碰撞的意思是计算得到的Hash值相同,需要放到同一个bucket中,HashMap中是采用链表法,单向链表

hash的计算规则?

(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

红黑树?

HashMap中的链表大小超过8个会自动转为红黑树,删除小于6个时变为链表,根据松坡分布,负载因子为0.75时,7个为分水岭,大于等于8转为红黑树,小于等于6转为链表

重写equals方法必须重写hashcode方法?

根据Object规范,如果两个对象的equals方法比较是相等的,那么调用任意一个对象的hashcode也必须产生同样的整数结果
原始equals是比较实例地址,hashcode是返回实例的虚拟内存地址,两个不同的实例在逻辑上是可能相等的,所以需要重写equals方法,hashcode也需要重写来确定两个实例返回一样的整数结果