首页 > 编程语言 >5.List源码面试题集锦

5.List源码面试题集锦

时间:2022-10-24 22:33:43浏览次数:54  
标签:面试题 集锦 删除 ArrayList 链表 源码 数组 大小 节点


1.新建一个ArrayList,现在add一个值,此时数组的大小是多少?下一次扩容前最大可用大小是多少?
答:此处数组的大小是1,下一次扩容前最大可用大小是10。因为ArrayList无参构造器初始化时,默认大小是空数组,第一次添加元素的时候进行扩容,大小是默认的10。

2.如果连续往ArrayList里面新增值,增加到第11个的时候,数组的大小是多少?
答:此时的数组大小是15。这里考查的是扩容公式,当增加到第11个元素的时候,此时希望数组的大小为11,但实际上数组的最大容量只有10,此时便需要扩容,扩容的公式是oldCapacity + (oldCapacity>> 1),oldCapacity表示数组现有大小,目前场景计算公式是10 + 10 / 2 = 15,然后发现11满足需求,因此数组的大小会被扩容到15。

3.数组初始化,被加入一个值后,如果使用addAll方法,一下加入15个值,那么最终数组的大小是多少?
答:最终数组的大小是16。第一题中已经计算出来数组在加入一个值后,实际大小是1,最大可用大小是10 ,现在需要一下加入15个值,那期望数组的大小值就是16,此时数组最大可用大小只有10,明显不够,需要扩容,扩容后的大小是10 + 10 /2 = 15,这时候发现扩容后的大小仍然不到期望的值16,这时,会采用源码中的如下策略:

//newCapacity本次扩容的大小,minCapacity期望的数组最小大小
//如果扩容后的值 < 期望值,期望值就等于本次扩容的大小
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;

所以最终数组扩容后的大小为16。

4.现在有一个很大的数组需要拷贝,原数组大小是5k,请问如何快速拷贝?
答:新建数组时指定新数组的大小为5k。因为原数组比较大,如果新建新数组的时候,不指定数组大小的话,就会频繁扩容,频繁扩容就会有大量的拷贝工作,造成额外的性能开销。

5.为什么说扩容会消耗性能?
答:扩容时,底层使用的是System.arraycopy方法,会把原数组的数据全部拷贝到新数组上,所以性能消耗比较严重。

6.有一个ArrayList,数据是 2、3、3、3、4,现通过for (int i = 0; i < list.size(); i++)的方式,把值为3的元素删除,请问可以删除干净么?如果删除不干净,那么最终删除的结果是什么,以及为什么会是这样的结果?

public static void main(String[] args) throws Exception {
List<String> list = new ArrayList<String>() {{
add("2");
add("3");
add("3");
add("3");
add("4");
}};
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("3")) {
list.remove(i);
}
}
}

答:不能删除干净,最终删除的结果是2、3、4,有一个3删除不掉。原因如下图所示,每次删除一个元素后,该元素后面的元素就会往前移动,而此时循环的i在不断增长。所以,删除第1个3后,第2个3会被遗漏,导致删不掉。

5.List源码面试题集锦_线程安全

7.对于6中的问题,可以通过增强for进行删除吗?
答:不可以,会报ConcurrentModificationException异常。因为增强for在循环时,调用的是迭代器的next ()方法,当调用remove()方法进行删除时,modCount的值会+1,而这时迭代器中的expectedModCount值却没有变,导致在迭代器下次执行next()方法时,expectedModCount != modCount就会报ConcurrentModificationException。

8.对于6中的问题,可以使用Iterator.remove()方法删除吗?
答:可以。因为Iterator.remove()方法在执行过程中,会把最新的modCount赋值给 expectedModCount,这样在下次循环时,modCount和expectedModCount就会相等。

9.ArrayList和LinkedList有何不同?
答:最大的不同是两者底层数据结构不同,ArrayList底层是数组,LinkedList底层是双向链表,两者的数据结构不同也导致了操作API的实现有所差异。拿新增实现来说,ArrayList会先计算并决定是否扩容,然后把新增的数据直接赋值到数组上,而LinkedList仅仅是改变插入节点和其前后节点的指向关系。其次是应用场景不同,ArrayList更适合快速查找匹配的场景,而LinkedList更适合频繁新增或删除的场景。

10.ArrayList和LinkedList两者有没有最大容量?
答:ArrayList有最大容量,最大容量为Integer的最大值,大于这个值JVM是不会为数组分配内存空间的,而LinkedList底层是双向链表,理论上可以无限大。但源码中,LinkedList实际大小用的是int类型,这也说明了LinkedList不能超过Integer的最大值,不然也会溢出。

11.ArrayList和LinkedList是如何对null值进行处理的?
答:ArrayList允许新增null值,也允许删除null值。删除null值时,是从头开始,找到第一值是null的元素删除。LinkedList新增删除时对null值没有特殊校验,也是允许新增和删除的。

12.ArrayList和LinedList是线程安全的吗,为什么?
答:当两者作为非共享变量时,比如说仅仅是作为方法里面的局部变量时,是没有线程安全问题的,只有当两者是共享变量时,才会有线程安全问题。主要的问题点在于多线程环境下,所有线程在任何时刻都可对数组和链表进行操作,这会导致值被覆盖,甚至混乱的情况。如果有线程安全问题,在迭代的过程中,会频繁报ConcurrentModificationException的异常,意思是在当前循环过程中,数组或链表的结构被其它线程修改了。

13.如何解决ArrayList和LinedList的线程安全问题?
答:Java源码中推荐使用Collections的synchronizedList方法进行解决,synchronizedList的返回值是所有方法都加了synchronized锁的list,保证了在同一时刻,数组和链表只会被一个线程所修改,或者采用CopyOnWriteArrayList来解决,这个类后面会详细说明。

14.你能描述下双向链表吗?
答:双向链表中双向的意思是说前后节点之间互相有引用,链表的节点称为Node。Node有三个属性组,前一个节点,本身节点和下一个节点,假设A、B节点相邻,A节点的下一个节点就是B,B节点的上一个节点就是A,两者互相引用。在链表的头部节点,称为头节点,头节点的前一个节点是null,尾部称为尾节点,尾节点的后一个节点是null,如果链表数据为空,头尾节点是同一个节点,本身值是null,指向前后节点的值也是null。

15.描述下双向链表的新增和删除?
答:新增时可以选择从链表头部新增,也可以选择从链表尾部新增,如果是从链表尾部新增的话,直接把当前节点追加到尾节点之后,本身节点自动变为尾节点。删除时把删除节点的后一个节点的prev指向其前一个节点,把删除节点的前一个节点的next指向其后一个节点,最后把删除的节点置为null即可。


标签:面试题,集锦,删除,ArrayList,链表,源码,数组,大小,节点
From: https://blog.51cto.com/u_15843693/5791483

相关文章

  • 4.LinkedList源码解析
    1.数据结构LinkedList底层数据结构是一个双向链表,整体结构如上图所示,链表中的每个节点都可以向前或者向后追溯。源码privatestaticclassNode<E>{//节点值Eite......
  • 3.ArrayList源码解析
    1.数据结构ArrayList的数据结构是一个数组,如上图所示,图中展示的是一个长度为10的数组,从1开始计数,index表示数组的下标,从0开始计数,elementData表示数组元素。除此之外,源码中......
  • 1.String源码解析
    1.不变性这里说的不变性指的是类值一旦被初始化,就不能再被改变了,如果被修改,将会是新的类,如程序1-1所示。//程序1-1publicclassApp{publicstaticvoidmain(String[......
  • 2.Integer源码解析
    1.取值范围和基本数据类型源码publicfinalclassIntegerextendsNumberimplementsComparable<Integer>{//该值用于定义Integer取值的最小值@Nativepublicst......
  • 认识 Redis client-output-buffer-limit 参数与源码分析
    概述Redis的​​client-output-buffer-limit​​可以用来强制断开无法足够快从redis服务器端读取数据的客户端。保护机制规则如下:[hardlimit]大小限制,当某一客户端缓......
  • WebRTC源码学习02---webrtc源码编译安装(Mac)
    参考文献https://webrtc.org.cn/mirror/ (主要参考文章)https://www.an.rustfisher.com/webrtc/intro/sync-build/(参考一下代理设置)https://blog.csdn.net/dangwei_90/ar......
  • 基于ssm高校科研管理系统-计算机毕业设计源码+LW文档
    【摘要】高校科研管理是一项重要而又繁琐的工作,有效的信息管理平台可以大大缓解科研管理压力,减少工作量。本文以石河子大学信息科学与技术学院为应用背景,开发教师教学信息......
  • 基于ssm工商学院办公用品管理信息系统设计与实现-计算机毕业设计源码+LW文档
    摘 要本高校科研管理系统设计目标是实现高校科研管理的信息化管理,提高管理效率,使得高校科研管理工作规范化、科学化、高效化。本文研究的高校科研管理系统基于SSM架构,采......
  • Vue源码解读之InitState
    前面我们讲到了_init函数的执行流程,简单回顾下:初始化生命周期-initLifecycle初始化事件-initEvents初始化渲染函数-initRender调用钩子函数-beforeCreate初始化依赖......
  • Vue3源码解读之patch
    例子代码本篇将要讲解domdiff,那么咱们结合下面的例子来进行讲解,这个例子是在上一篇文章的基础上,加了一个数据变更,也就是list的值发生了改变。html中增加了一个按钮change......