HashMap常见面试题(版本区别、锁升级、扩容、hash冲突及面试对话)

4 篇文章 0 订阅

纯面试 纯文字 看起来乱但适合面试总结

HashMap

hashmap 1.7

1.7 数据结构:使用的是数组加链表,他数据节点是一个Entry节点,它的一个内部类,他的数据插入的过程是使用头插法,所以会产生一个问题。他在resize,也就是说他的扩容的一个过程,可能会造成就是在里面有一个resize的方法,他又调用了一个transfer的方法把里面的一些Entry进行了一个rehash,刚才这个过程当中,可能会造成一个链表的一个循环。就可能在下一次Get的时候出现一个死循环的情况,也有可能就是因为他没有加锁,所以他也有可能多个线程并发的情况下,可能对他的数据不能保证它是一个安全的,就是我push的进去的值,取出来的还是我push进去的一个值 (会死循环,造成线程不安全的原因之一

hashMap1.7的时候,他的底层数据结构是一个数组加上一个单链表。它再PUT的时候还有一个Resize的过程,这个过程会造成它的头插会形成一个环形链表导致一直死循环

hashmap 1.8

JDK1.8以后对他进行了一个比较大的一个变化,尾插法,他不会出现一个链表循环的这么一个过程,就主要是,把他变成了一个链表加数组 加红黑树的这么一个结构,把原来的一个Entry节点也变成了一个Node节点,他整个put的过程也做了一个优化,线程一样不安全,可以使用ConcurrentHashMap这样一个线程安全的这样一个集合容器(还有HashTable,或者就是加Synchronized,或者Lock,或者Conllection.Synchronized都可以对它进行一个同步的操作),(ConcurrentHashMap)他的并发度是更高的,因为就是在我看来就是ConcurrentHashMap,我们知道,就是普通的HashTable是直接对里面的方法进行了一个Synchronized的就是加了一个对象锁,但是ConcurrentHashMap数据结构就是1.8之后 变成了就是同样的数组加链表加红黑树,它只会锁住,就是我目前获取到的那个Entry所在的那个节点的一个值,然后在上锁的时候它使用了就是 CAS Synchronized然后再加上JDK1.6以后对Synchronized进行了一个优化所升级的一个过程,所以他的一个效率是更高的,就是他支持的并发度是更高的。

hashMap1.8的时候,他的底层数据结构是一个数组加上一个单链表或者一个红黑树的一个方式,当单链表和红黑树之间的转换,它的单链表的长度大于等于八,并且它的hash桶大于等于64的时候,它会将单链表转换成红黑树行使存储。它在红黑树的节点的数量如果是小于等于6的时候,它会重新再转成一个单链表。这是它底层结构的一个变化。另外一点就是关于它hash桶的数量,他的数量默认是16个,他的阈值默认是0.75,还关系到它的扩容,扩容的时候它是首先会检测数组里的元素个数,因为有loadFactor的默认值为0.75,它含有的桶数默认是16,它的阈值是16*0.75=12,当它哈希桶占用的容量大于的12的时候,它就会触发扩容,它的扩容成之前哈希桶容量的二倍,它会同乘2的N次幂,会把之前那些元素再次进行一次哈希运算,然后添加到新的哈希桶里面,是按照链表或者红黑树的方式再排列起来。它不是线程安全的,在插入操作的时候多线程会有数据覆盖的问题。

你怎么保证它的线程安全:我平时会使用ConcurrentHashMap替代来保证它的线程安全(还有HashTable或Conllection.synchronized来替代,为什么选择了ConcurrentHashMap),因为他是通过锁分段实现的,性能更强

Hashmap是有序的吗?

不是,有序的Map实现类有TreeMap和LinkedHashMap

TreeMap和LinkedHashMap是怎么保证它的顺序的?

LinkedHashMap会存储数据的插入顺序,是进入时有序;TreeMap则是默认key升序,是进入后有序(hashMap 、hashTable无序),但是可以通过重写TreeMap的比较器修改默认排序

LinkedHashMap继承自 HashMap,具有高效性,同时在 HashMap 的基础上,又在内部增加了一个链表,用以存放元素的顺序。

TreeMap 则提供了一种完全不同的 Map 实现。从功能上讲,TreeMap 有着比 HashMap 更为强大的功能,它实现了 SortedMap 接口,这意味着它可以对元素进行排序。

LinkedHashMap:是一个维持双向链表,是一个有序的Map,怎么put的进去的输出时怎么取出,FIFO的顺序

TreeMap: 在需要排序的时候使用,在一个map放入很多数据,需要按照什么规则排序显示的时候。

锁升级的过程

在最开始的时候是无锁的状态,它一上来会去判断一下,然后再升级,就是我们这个锁是有支持偏向锁的,我当前获取到锁资源的过程,我会优先让它再去获取到这个锁,如果他没有获取到这个锁,就升级成一个轻量级的,一个CAS的锁就是一个乐观锁,乐观锁的时候它是一个比较有交换的过程,如果这个CAS,没有设置成功的话,他会进行一个自旋。自旋到一定的次数之后才会升级成一个Synchronized的就是这么一个重量级的锁。这样的话,就保证了它的一个性能的问题

扩容机制

扩容首先要了解的就是capacity这个节点,就是我在初始化这个hashmap的时候,如果没有设置他的capacity,他的默认初始化容量是16,负载因子是0.75,他会计算出来一个threshold,就是他的一个阈值,就是一个扩容的一个阈值,如果当我在put的时候我会先判断我当前这个size是不是要大于这个阈值,如果大于的时候,他就会新创建出来一个两倍大小,他会扩容成原来的两倍,将原来的一个Entry进行一个resize的这么一个过程

HashMap的Hash冲突处理办法

**hash冲突:**就是根据key即经过一个函数f(key)得到的结果的作为地址去存放当前的key value键值对(这个是hashmap的存值方式),但是却发现算出来的地址上已经有人先来了。就是说这个地方被抢了啦。这就是所谓的hash冲突啦。

哈希函数处理冲突的方法

1.开放定址法

2.链地址法

3.再哈希

4.建立公共溢出区

hashmap出现了Hash冲突的时候采用第二种办法:链地址法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值