0
点赞
收藏
分享

微信扫一扫

Map相关面试答案(都是简单版

止止_8fc8 04-13 18:00 阅读 0
面试java

一、HashMap的扩容机制

在1.7中
1、先生成新数组
2、遍历老数组中每个位置上的链表的所有节点
3、取每个节点的key,计算出每个元素在新数组中的下标,并添加到新数组中,这里用的是头插法
4、转移完毕后将新数组复制给hashMap的table属性

1.7中扩容的问题,使用的是头插法,扩容后改变链表顺序可能引起链表节点死循环。

在1.8中
1、先生产新数组
2、遍历老数组每个位置上的链表或者红黑树
3、遍历链表/红黑树里的每个元素,计算在新数组中的下标位置,使用尾插法
4、这里在插入时,如果该位置的元素超过8,就生成一个新的红黑树,并将根节点添加到新数组的相应位置。如果没超过8,就生成一个链表,并将链表的头节点添加到新数组的响应位置。
5、所有元素转移后,将新数组赋值给hashMap的table属性

链表大于8/数组大于等于64时转成红黑树,红黑树小于6转成链表。

为什么是8:泊松分布。

二、HashMap的put

1、根据key通过哈希算法和与运算计算出数组下标
2、如果数组下标为空,将key和value封装成Entry对象,1.8中是Node对象,并放入该位置
3、如果数组下头节点不为空,分情况讨论
3.1、1.7中,需要判断是否扩容,如果要扩容就进行扩容,不扩容就生成Entry,头插法插入到链表中。
3.2、1.8中,会先判断当前数组的是红黑树还是链表

  • 如果是红黑树,就将key和value封装成一个Node,添加到红黑树中,如果红黑树有这个key,就修改这个node的value,否则就插入。
  • 如果是链表,遍历链表,使用尾插法插入,如果链表此时长度大于等于8,需要转成红黑树。
    4、在插入后,也需要判断是否需要扩容。

二、hashmap和hashtable的区别

hashmaphashtable
非线程安全线程安全
key和value可以为nullkey不可以为null
继承自abstractMap继承自directory
数组+链表实现哈希表实现,默认size=11

三、LinkedHashMap

1、维护一条双向链表,就是在hashMap的基础上,链表/红黑树的节点都有一个前后指针,指向上次插入的节点和下次插入的节点。
2、适合LRU算法,最近最少使用
3、迭代顺序和插入顺序一样,插入较hashmap效率低

四、TreeMap extend AbstractMap

1、继承
2、红黑树实现,返回有序的key
3、在创建时需要提供comparator来排序

五、ConcurrentHashMap

1、在hashmap的基础上增加并发安全,数据结构和hashmap一样。
2、多线程并发扩容:多个线程对原始数组进行分片,每个线程进行一片数据的迁移。
3、

  • 1.7中,使用的是分段锁,segemnt,将一个范围内的数组元素放一块,锁的时候一起锁,基于ReentrantLock重入锁的实现。
  • 1.8 用CAS volatile synchronized通过对头节点加锁,锁的粒度变小。

ConcurrentHashMap 和hashtable都是线程安全的有什么区别

ConcurrentHashMaphashTable
ConcurrentHashMap的锁性能比hashtable好hashtable是锁一整个表的
ConcurrentHashMap的迭代器支持边迭代边修改hashtable不支持迭代时修改
举报

相关推荐

0 条评论