Java集合框架-----Map集合常问面试题整理

  • 文章参考:求求大厂给个offer:Map面试题(java3y)

Map(jdk1.8)

1.对Map的了解?

  • Map在Java中是一个接口,常见的实现类有HashMap、 LinkedHashMap、TreeMap和ConcurrentHashMap
  • 首先要明确的是,在Java中,哈希表的结构是数组+链表的方式。HashMap底层数据结构是数组+链表/红黑树、LinkedHashMap的底层数据结构是数组+链表+双向链表、TreeMap底层数据结构是红黑树,而ConcurrentHashMap的底层数据结构也是数组+链表/红黑树

2.HashMap,你能讲讲当你new一个HashMap的时候,会发生什么吗?

  • HashMap有几个构造方法,但最主要的就是指定初始值的大小和负载因子的大小,如果我们不指定,默认HashMap的大小为16.负载因子为0.75
  • HashMap的大小只能是2次幂,假设你传入了10进去,实际上最终的大小为16,你传入7,实际为8,具体的实现可以在tableSizeFor可以看到。我们把元素放进HashMap的时候,需要算出这个元素所在的位置(hash)。在HashMap里用的是位运算来代替取模,能够更加高效的算出该元素所在的位置,为什么HashMap的大小只能为2次幂呢?因为只有大小为2次幂时,才能合理运用位运算来代替取模
  • 负载因子的大小,决定了哈希表的扩容和哈希冲突,比如现在我默认的HashMap大小为16,负载因子为0.75,这意味着数组最多只能存放12个元素,一旦超过12个元素,则哈希表需要扩容,16*0.75.每次put元素进去的时候,都会检查HashMap的大小有没有超过这个阈值,如果有,则需要扩容。因为HashMap的大小只能是2次幂,所以扩容的时候默认是扩大为原来的2倍。
  • 扩容这个显然是耗时的,那我能不能把负载因子调高一点,比如我要调到为1,那我的HashMap就要等到16个元素的时候才扩容,显然是可以的,但是不推荐这么做,负载因子调高了,这意味着哈希冲突的概率会增高,哈希冲突概率增高,同样会耗时(因为查找的速度变慢了)

3.在put元素的时候,传递的key是怎么计算哈希值的?

  • 实现就在hash方法上,可以发现的是,它是先算出正常的哈希值,然后与高16位做异或运算,产生最终的哈希值,这样做的好处可以增加了随机性,减少了碰撞冲突的可能性。

4.HashMap的put/ get方法的实现?

  • 在put的时候,首先先对key做hash运算,计算出该key所在的index,如果没有碰撞,直接放到数组中,如果碰撞了,需要判断目前数据结构是链表还是红黑树,根据不同的情况来进行插入。假设key是相同的,则替换到原来的值,最后判断哈希表是否满了(当前哈希表大小*负载因子),如果满了,则扩容
  • 在get的时候,还是对key做hash运算,计算出该key所在的index,然后判断是否有hash冲突,假设没有直接返回,假设有则判断当前数据结构是链表还是红黑树,分别从不同的数据结构中取出

5.在HashMap中,怎么判断一个元素是否相同的呢?

  • 首先先比较hash值,随后会用==运算符和equals方法来判断该元素是否相同。如果只有hash值相同,那说明该元素哈希冲突了,如果hash值和equals || == 都相同,那说明该元素是同一个

6. HashMap的数据结构是数组+链表/红黑树,那什么情况才会用到红黑树?

  • 当数组的大小大于64且链表的大小大于8的时候才会将链表改为红黑树,当红黑树大小为6时,会退化位链表。这里转红黑树退化位链表的操作主要出于查询和插入时对性能的考量。链表的查询时间复杂度位O(1),插入时间复杂度为O(1),红黑树查询和插入时间复杂度为O(logN).

7.HashMap是线程安全的吗?(了解ConcurrentHashMap吗?)

  • 不是,在多线程环境下,HashMap有可能会有数据丢失和获取不了最新数据的问题,比如说,线程Aput进去了,线程Bget不出来。我们想要线程安全,可以使用ConcurrentHashMap
  • ConcurrentHashMap是线程安全的Map实现类,它在juc包下的,线程安全的Map实现类除了ConcurrentHashMap还有一个叫做HashTable,当然了,也可以使用Collections来包装出一个线程安全的Map(比如:synchronizedList,synchronizedMap),但无论是HashTable还是Collectiions包装出来的都比较低效(因为是直接在外层套synchronize),所以我们一般有线程安全问题考量的,都是用ConcurrentHashMap
  • ConcurrentHashMap的底层是数组+链表/红黑树,它能支持高并发的访问和更新,是线程安全的。它通过在部分加锁和利用CAS算法来实现同步,在get的时候没有加锁,Node都用了volatile来修饰。在扩容时,会给每个线程分配对应的区间,并且为了防止putVal导致数据不一致,会给线程所负责的区间加锁
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值