当前位置: 首页 > 后端技术 > Java

在线面试官-别再问我JavaList套路篇

时间:2023-04-01 18:14:49 Java

本期是【在线面试官】系列文章的第二期,主要讲JavaList高频面试题。回复【面试】获取大斌精心整理的大厂面试手册,帮助众多小伙伴拿下大厂offer!面试现场面试官:你好,我是面试官xxx,你是大斌吗?大斌:面试官你好,我是大斌面试官:现在方便面试吗?大斌:对对对。采访者:现在开始采访吧。面试官:我看你简历上对收藏很熟悉。你知道Java的List吗?大斌:嗯,List是一个接口,常见的实现类有ArrayList和LinkedList面试官:说说这两个实现类的区别?独白:老八股文哈哈大斌:ArrayList底层数据结构是数组,支持下标访问,数据快速查询。默认初始值为10,容量不足时会扩容。大斌:LinkedList的底层数据结构是一个链表,元素添加到链表的末尾,不展开。面试官:嗯,你刚才提到了ArrayList的扩展。告诉我?独白:好家伙,我就知道你会问这个,八字都准备好了。大彬:ArrayList宽容源码实际如下:publicbooleanadd(Ee){ensureCapacityInternal(size+1);//扩展elementData[size++]=e;returntrue;}privatevoidensureCapacityInternal(intminCapacity){if(elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA){minCapacity=Math.max(DEFAULT_CAPACITY,minCapacity);}ensureExplicitCapacity(minCapacity);}privatevoidensureExplicitCapacity(intminCapacity){modCount++;//溢出意识代码if(minCapacity-elementData.length>0)grow(minCapacity);}privatevoidgrow(intminCapacity){//溢出意识代码intoldCapacity=elementData.length;intnewCapacity=oldCapacity+(oldCapacity>>1);如果(newCapacity-minCapacity<0)newCapacity=minCapacity;如果(newCapacity-MAX_ARRAY_SIZE>0)newCapacity=hugeCapacity(minCapacity);//minCapacity通常接近大小,所以这是一个胜利:elementData=Arrays.copyOf(elmentData,newCapacity);}大斌:可以看到,在grow方法中扩容,将数组容量扩大到原来的1.5倍大斌:比如初始值为8,当加入第9个元素时发现数组空间不够,就扩容,扩容后容量为12。大斌:扩容后会调用Arrays.copyOf()方法复制数组。面试官:嗯,对,ArrayList和LinkedList适合什么场景?大斌:对于随机索引访问的get和set方法,ArrayList的速度要优于LinkedList。因为ArrayList直接通过数组下标直接找到元素;LinkedList需要移动指针遍历每一个元素,直到找到为止。大斌:LinkedList在增删元素方面比ArrayList快。因为ArrayList在增删元素时可能会扩充和复制数组;而LinkedList的增删改查操作只需要修改指针即可。大斌:所以ArrayList适合查询多,增删改查少的场景。而LinkedList适用于查询少,增删多的场景。面试官:说说Set和List的区别?大斌:List使用索引访问元素,有序,元素允许重复,可以插入多个null;Set不能存储重复元素,无序,只允许插入一个null。大斌:List的底层实现有两种方式:数组和链表;Set是基于Map实现的,Set中的元素值就是Map的键值。面试官:你知道Vector吗?大斌:嗯,Vector的底层结构是一个数组,现在基本不用Vector了,因为操作Vector的效率比较低。与ArrayList相比,它是线程安全的,扩容时容量翻倍。面试官:嗯,你知道线程安全的列表吗?大彬:可以使用Collections.synchronizedList()方法返回一个线程安全的List。大斌:还有一个办法,就是CopyOnWriteArrayList。面试官:嗯,刚才你提到了CopyOnWriteArrayList,详细解释一下它的原理?独白:这个太麻烦了,底层原理有分歧...大斌:CopyOnWriteArrayList是一个线程安全的List,底层是通过复制数组来实现的。大斌:所谓CopyOnWrite就是copy-on-write。大斌:我们往容器中添加元素的时候,并不是直接往容器中添加元素。相反,我们首先复制当前容器以创建一个新容器,然后将元素添加到新容器中。添加完元素后,我们将原来的容器A引用复制到新的容器中。大斌:这样做的好处是可以不加锁的并发读取CopyOnWrite容器,因为不会修改当前容器。publicbooleanadd(Ee){finalReentrantLocklock=this.lock;锁.锁();//add方法需要锁定try{Object[]elements=getArray();intlen=elements.length;对象[]newElements=Arrays.copyOf(元素,len+1);//复制新数组newElements[len]=e;设置数组(新元素);//原容器的引用指向新容器returntrue;}最后{lock.unlock();}}面试官:能说说CopyOnWriteArrayList的缺点吗?大斌:主要有两个问题。大斌:内存占用问题。由于CopyOnWrite的copy-on-write机制,当进行写操作时,两个对象的内存会同时驻留在内存中。大斌:CopyOnWrite容器不能保证数据的实时一致性,可能会读取到旧数据。采访者:嗯,是的。面试官:问一些开发中经常遇到的问题,List如何排序?大斌:可以使用list本身的sort方法,也可以使用Collections.sort(list)方法。面试官:如何在遍历ArrayList时移除一个元素?大斌:如果用foreach删除元素,会造成fast-fail的问题。您可以使用迭代器的remove()方法来避免快速失败问题。迭代器itr=list.iterator();while(itr.hasNext()){if(itr.next().equals("dabin"){itr.remove();}}面试官:基础还不错!回去等通知大斌:好的,谢谢你的独白:回去等通知?不会冷吧……