2023 Java后端面经精简(集合篇)

建议:集合的话主要看以下几个就可以了(工作两年以上),应届生的话尽量都看,集合的源码去看一下不多的。

LinkedList:

开发基本用不上这个集合,因为我们取数据的时候一般用ArrayList接,我们一般也不会对其进行增删,更多的是修改。
采用的是链表的数据结构,相比较ArrayList更适合删除和添加比较多的场景下使用。
链表物理存储上是非连续的。各元素之间的逻辑顺序是通过链表的指针地址实现的。
LinkedList的基础结构

ArrayList:

采用的是数组的数据结构,相比较LinkedList更适合在查询较多的场景下使用(因为每当向数组中添加元素时,都会去检查添加后元素的个数是否会超出当前数组的长度,如果超出,就会扩容,扩容是通过复制引用的方式来实现的,所以不适合在增删比较多的情况下会比LinkedList慢),默认大小是10,扩容是原数组的1.5倍(原数组的长度+原数组长度右移一位)。
数组是通过一块连续的内存空间存储的,并且每个节点的大小相同,所以可以通过索引快速查找。
在这里插入图片描述
在这里插入图片描述

HashSet:

基于Hashmap实现,key就是存入的值,Hashmap中不允许key重复,value就是一个伪值(new Object)。
在这里插入图片描述
集合结束后,一般也会问Map,所以HashMap和ConcurrentHashMap一定要会。

HashMap:

kv键值对的形式,主要的数据结构是数组+链表(红黑树),默认大小是16,负载因子是0.75,扩容的话是原大小的两倍(这样的操作有利于key在数组中的均匀分布)。key在数组中的 index 是通过 (key.hasCode & 数组长度 - 1)算出来的。1.7会出现死循环的问题,因为1.7还用的头插法,所以两个线程在同时操作的时候可能会出现问题。1.8改成了尾链法,解决了这个问题,不过在高并发的情况下还是去使用ConcurrentHashMap。
在这里插入图片描述
下面两个图就解释了HashMap的基础结构
在这里插入图片描述
在这里插入图片描述
最重要的是putValue这个方法, 这个方法先是判断这个index的位置有没有值,没有的话直接将value值插入,如果有的话通过equal()方法是否相同,相同的话覆盖,不同的话使用尾插法将value插入,当链表的长度大于8并且数组大于64的时候会将链表转化外红黑树,这样的操作时为了加快查询速度(将查询速度从O(n)优化到O(logn)),插入成功会检查是否需要扩容。
在这里插入图片描述

ConcurrentHashMap:

(不重要)jdk1.7及之前,是通过Segment分段锁来实现的,将一个数组分成几段来实现,当某个段很大的时候性能会下降。
在这里插入图片描述
在这里插入图片描述
(重要!)jdk1.8之后,是通过synchronizd和CAS来保证线程安全的,进一步实现锁细化的概念,在put和transfer的操作会加锁,具体的话是通过Synchronized锁住Node,用CAS来替换值。
在这里插入图片描述
在这里插入图片描述

附:HashMap的几个问题

为什么HashMap的容量会小于数组长度?

如果容量大于数组很多的话再加上散列算法不是很优秀的情况下容易出现链表过长的情况,这样会降低查询速度
同时由于负载因子的存在,容量就不会等于数组长度的情况

ConcurrentHashMap在扩容期间在未迁移到hash桶插入数据时会发生什么?

只要插入的位置扩容线程还未迁移到(还没轮到),就可以插入,当迁移到该插入的位置时,就会阻塞等待插入操作完成再继续迁移 。

ConcurrentHashMap正在迁移的hash桶遇到get操作会怎么样?

get操作不会阻塞,因为迁移期间是用的类似复制引用的方式,所以原hash桶上的数据不会收到影响,因此会正常访问原hash桶上的数据,如果查询的桶被迁移了,就会通过ForwardingNode的指针去查已扩容的新数组

并发情况下,各线程数据下可能不是最新的,那为什么get方法不加锁?

因为Node成员的value使用volatile修饰的

ConcurrentHashMap中的key和value可以为null吗?为什么?

不可以,因为源码中是这样判断的,进行put()操作的时候如果key为null或者value为null,会抛出NullPointerException空指针异常。
如果ConcurrentHashMap中存在一个key对应的value是null,那么当调用map.get(key)的时候,必然会返回null,那么这个null就有两个意思:这个key从来没有在map中映射过,也就是不存在这个key;这个key是真实存在的,只是在设置key的value值的时候,设置为null了;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值