HashMap面试问题总结

Q:JDK8中的HashMap与JDK7中的有什么区别
A:
1.JDK8中的HashMap由数组加链表,变成了数组加链表加红黑树组成。如果链表长度大于8,并且总的元素个数大于一定的阈值,则转为红黑树。
2.JDK7中的链表扩容时使用的是头插法,JDK8中改成了尾插法
3.JDK8中的因为使用了红黑树保证了插入和查询了效率,JDK8中的Hash算法实现的复杂度降低了
4.JDK8中数组扩容的条件只会判断是否当前元素个数是否查过了阈值,不再判断当前put进来 的元素对应的数组下标位置是否有值。

Q:HashMap中PUT方法的流程?
A:
1.根据key,来算一个hash值。确认所在的数组下标
2.如果数组下标所在的node是空的,直接插入。如果不是空的,则遍历链表。然后看看是否存在同样的key。如果存在,则更新。不存在的插入
3.JDK7用的是头插法。JDK8用的是尾插法,遍历过程中发现链表长度大于8,则转为红黑树,然后再把值插入

Q:JDK8中链表转为红黑树的条件
A:
1.链表的长度大于8
2.还需要当前的数组长度大于64.因为链表过长的时候,如果数组长度不够长,可以先扩大数组长度来解决
3.当红黑树的节点变成6的时候,会转为链表,为什么不是小于8的时候就转为链表呢?防止频繁从8到7,从7到8.频繁转化

Q:HashMap扩容流程是怎样的
A:
1.扩容是数组的扩容,数组在内存中需要连续,一旦扩容的时候内存中没有足够的空间,就得gc.清理内存,然后再复制一个双倍长度的数组.然后再将老数组上的数据迁移到新数组上
2.那流程就是先创建一个双倍长度的数组
3.JDK7中就是遍历数组的每个下标,根据新数组的长度,计算每个元素的hashcode值,然后放到新数组中去。有些链表的长度就变小了
4.JDK8中存在红黑树,就比较复杂了,HashMap中维护了一个双向链表。如果转移的过程中发现是红黑树的话,遍历双向链表,判断哪些元素会到新的位置,哪些依旧在老位置,遍历完后,就会得到2个链表。如果其中有个链表是空的,则直接将红黑树转移到对应的位置。否则将链表转移到对应的位置,如果链表长度大于8,则转为红黑树

Q:HashMap在JDK7中为什么会引起循环链表问题,而JDK8中不会呢。
A:JDK7中对链表的插入是头插法。比如A,B2个元素,hashcode都一致,就组成了链表,如果B先put,A再put。则链表关系为A-B。然后2个线程线程1与线程2同时判断需要对这个线程进行扩容,线程1先执行。假设A与B扩容后的节点还是一个,则A先转移到新数组,然后当前链表引用就变成了B。此时线程2继续执行。A节点开始转移,然后再转移B节点,但是因为是头插法,则就是B->A。然后线程1继续执行。B执行完了后,下个节点就是A,然后A的下个节点又是B。
而JDK8中是使用的尾插法,不会修改链表的引用关系

你可能感兴趣的:(HashMap面试问题总结)