北大面试集合部分

北大面试集合部分

  • 1.前言
  • 2. 集合部分

1.前言

是敖丙出的一个面试的视频,面试的人是北大的硕士有两年的工作经验。
程序员面试北大研究生Java岗,中途离场,是不是玩不起?

2. 集合部分

Q1:集合你平时用的多的有哪些
集合的话像Collection下的ArrayList、LinkedList,像Set集合中的HashSet,另外再Map中比较常用的是HashMap设计到线程安全的话可能会用到ConcurrentHashMap

Q2:我们先聊一下ArrayList和LinkedList吧还有它们两个使用的场景
首先ArrayList它底层是数组,它初始化的时候它的数据量是零,当你add的时候它会默认变成10,它的扩容每次扩容是它之前容量的1.5倍,它的特性是查找比较快,它的删除效率比较低。LinkedList的底层是带有头结点和尾结点的双向链表,它提供两种插入方式一个是头插LinkedFirst还有一个尾插LinkedLast,它的特性非常适合经常增加、删除操作的场景。它的查询在量大的时候会比较慢。它在查询的时候是链表查询,查询的时候会拿值按照顺序从第一个开始一个一个的进行比较;而ArrayList查询是根据脚标查询的,所以会很快。
北大面试集合部分_第1张图片
Q3:如果遇到线程安全的一些情况下,但是你又想使用List的情况怎么办?
这个有一个解决的办法就是使用一个老土的Vector,它跟ArrayList一样底层都是一个数组,它与ArrayList有一点区别是它其中大部分方法都被Synchronized关键字所修饰,所以说他是一个线程安全的。它扩容的时候与ArrayLst还有点区别,它的扩容大小是2倍进行扩容的。

Q4:刚才你还提到了Map包下面的像HashMap,我们就聊一下HashMap
Map集合下常用的有HashMap首先HashMap主要用来放键值对,它是基于哈希表的Map接口实现的,是非线程安全的,HashMap可以存储值为null的key和value,但null作为key只能有一个而作为value却可以有很多个,在jdk1.7的时候它的底层是一个数组加上一个单链表,数组是HashMap的主体,链表是为了解决哈希冲突而存在的(“拉链法解决”),到了1.8的时候就变成了数组加上单链表或者说是红黑树的方式,单链表和红黑树之间相互转换。他的单链表长度≥8,并且他的数组长度≥64的时候,它的单链表会转化成红黑树的形式。
它在红黑树的节点数量,如果要是小于6的时候,它会重新再转化成一个单链表这是他底层的一个变化,另外一点就是关于它的数组的数量,默认是16,他的阈值是0.75,这还关乎到它的扩容。
扩容的时候HashMap会检查数组里元素的个数,因为有loadFactor的默认值是0.75,它的数组长度默认是16,阈值为0.75,16*0.75=12,当他的数组长度大于12的时候,他就会触发扩容,扩容成之前哈希桶长度的而被(哈希表总以2的幂作为哈希表的大小),然后把之前元素重新进行一次哈希计算,然后添加到新的数组里面。

Q5:你跟我说一下它是不是线程安全的
它不是线程安全的,因为他在插入的时候多线程会有数据覆盖的可能。另外再1.7的时候,在put的时候会有一个resize的过程,这个过程会造成它的头插,会形成一个环形链表导致一直死循环。在1.8的时候改成尾差了

Q6:如果要用线程安全的Map呢
直接使用ConcurrentHashMap替代来保证它的线程安全

Q6:还有个HashTable或者Collection.Synchronized来代替

Q7:你跟我聊一下ConcurrentHashMap
首先它的数据结构在1.7版本底层是个分片数组,它为了保证线程安全它他有个Segment锁,这个Segment继承于ReentrantLock来保证它的线程安全的,它每次只给一段加锁来保证它的并发度。另外在1.8的时候它改成了和HashMap一样的数据结构。数组加单链表或者红黑树的数据结构,在1.8版他会逐渐放弃这种分片锁机制,而使用Synchronized和CAS来操作,因为在1.6版的时候JVM对Synchronized的优化非常大,它现在也是用这种方法来保证它的线程安全。
北大面试集合部分_第2张图片
Q8:刚才你提到了1.7版之前Segment分段锁,那你知道它如果要找到具体的值,他会经过几次哈希吗?或者它是如何去找到一个具体数值的?
这个候选人没有看过!

Q9:刚说1.8版之后它是CAS加Synchronized,那CAS(Compare And Swap)是什么?
CAS相当于一个轻量级的加锁的过程,比如说你要修改一个但在并发量不是特别大的情况下,锁竞争不激烈你要修改东西,你要先查,查完之后再修改,修改完准备写之前,它会再查一次,比较之前的结果有没有区别,如果有区别的话说明这个修改是不安全的,如果没有修改说明是安全的,这时它可以安全的去修改。而不是直接加锁的那种形式。在低并发的情况性能可能会好一点的。

比较并替换(Compare And Swap)

Q10:它有什么优缺点,刚才你说优点是轻量级,那在高并发情况下大量使用它,它有什么缺点呢?
首先当并发量特别大的时候,它始终有个忙循环的过程对CPU的性能消耗还是比较大的,当高并发的时候直接使用状态机,锁之类的,另外一个他可能会产生一个ABA的问题,之前读和过段时间读中间会被第三人修改过, 但是它又给改回来了。这个问题可以通过添加一个戳或者标志位来解决。

北大面试集合部分_第3张图片
北大面试集合部分_第4张图片
Q11:刚才你提到了Synchronized,在跟我聊下它
关于Synchronized。可以比如说同步代码块,还有它同步代码块时可以指定任意的锁,对象作为锁,当它应用于方法上,它的锁就是this,如果要是静态方法则锁定是它的class对象,关于Synchronized在JDK1.6时候升级还是蛮大的。
// TODO 11:37
北大面试集合部分_第5张图片

你可能感兴趣的:(Java集合,面试,java,链表)