1.1 说说你自己对 ArrayList 的理解?
很多面试官喜欢这样子开头,考察面试同学对 ArrayList 有没有总结经验,介于 ArrayList 内容
很多,建议先回答总体架构,再从某个细节出发作为突破口,比如这样:
ArrayList 底层数据结构是个数组,其 API 都做了一层对数组底层访问的封装,比如说 add 方
法的过程是……(这里可以引用我们在 ArrayList 源码解析中 add 的过程)。
一般面试官看你回答得井井有条,并且没啥漏洞的话,基本就不会深究了,这样面试的主动权就
掌握在自己手里面了,如果你回答得支支吾吾,那么面试官可能就会开启自己面试的套路了。
说说你自己对 LinkedList 的理解也是同样套路。

<>1.2 扩容类问题

1.2.1 ArrayList 无参数构造器构造,现在 add 一个值进去,此时数组的大小是多少,下一次扩容前最大可用大小是多少?
答:此处数组的大小是 1,下一次扩容前最大可用大小是 10,因为 ArrayList 第一次扩容时,
是有默认值的,默认值是 10,在第一次 add 一个值进去时,数组的可用大小被扩容到 10 了。

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

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

1.2.4 现在我有一个很大的数组需要拷贝,原数组大小是 5k,请问如何快速拷贝?

答:因为原数组比较大,如果新建新数组的时候,不指定数组大小的话,就会频繁扩容,频繁扩容就会有大量拷贝的工作,造成拷贝的性能低下,所以回答说新建数组时,指定新数组的大小为5k
即可。

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

1.2.6 源码扩容过程有什么值得借鉴的地方?
答:有两点:
1.是扩容的思想值得学习,通过自动扩容的方式,让使用者不用关心底层数据结构的变化,封装得很好,1.5
倍的扩容速度,可以让扩容速度在前期缓慢上升,在后期增速较快,大部分工作中要求数组的值并不是很大,所以前期增长缓慢有利于节省资源,在后期增速较快时,也可快速扩容。
2.扩容过程中,有数组大小溢出的意识,比如要求扩容后的数组大小,不能小于 0,不能大于Integer 的最大值。
这两点在我们平时设计和写代码时都可以借鉴。

<>删除类问题

2.1 有一个 ArrayList,数据是 2、3、3、3、4,中间有三个 3,现在我通过 for (int i=0;i<list.size ();i++)
的方式,想把值是 3 的元素删除,请问可以删除干净么?最终删除的结果是什么,为什么?删除代码如下:

答:不能删除干净,最终删除的结果是 2、3、4,有一个 3 删除不掉,原因我们看下图

从图中我们可以看到,每次删除一个元素后,该元素后面的元素就会往前移动,而此时循环的 i 在不断地增长,最终会使每次删除 3 的后一个 3
被遗漏,导致删除不掉。

还是上面的 ArrayList 数组,我们通过增强 for 循环进行删除,可以么?
不可以,会报错。因为增强 for 循环过程其实调用的就是迭代器的 next () 方法,当你调用list#remove () 方 法 进 行 删 除 时
,modCount 的 值 会 +1 , 而 这 时 候 迭 代 器 中 的expectedModCount 的 值 却 没 有 变 , 导 致 在 迭 代
器 下 次 执 行 next () 方 法 时 ,expectedModCount != modCount 就会报
ConcurrentModificationException 的错误。
//其实错误得根源就是增强的for循环是迭代器方式访问,会需要判断expectedModCount !=
modCount而删除元素用的是集合中的remove而不是迭代器中的remove删除之后没有将当前的modCount赋值给expectedModCount.

还是上面的数组,如果删除时使用 Iterator.remove () 方法可以删除么,为什么?
答:可以的,因为 Iterator.remove () 方法在执行的过程中,会把最新的 modCount
赋值给expectedModCount,这样在下次循环过程中,modCount 和 expectedModCount 两者就会相等。
ArrayList 和 LinkedList 两者有没有最大容量
答:ArrayList 有最大容量的,为 Integer 的最大值,大于这个值 JVM 是不会为数组分配内存
空间的,LinkedList 底层是双向链表,理论上可以无限大。但源码中,LinkedList 实际大小用
的是 int 类型,这也说明了 LinkedList 不能超过 Integer 的最大值,不然会溢出。
ArrayList 和 LinkedList 是如何对 null 值进行处理的
答:ArrayList 允许 null 值新增,也允许 null 值删除。删除 null 值时,是从头开始,找到第一
值是 null 的元素删除;LinkedList 新增删除时对 null 值没有特殊校验,是允许新增和删除的。
ArrayList 和 LinedList 是线程安全的么,为什么?

答:当两者作为非共享变量时,比如说仅仅是在方法里面的局部变量时,是没有线程安全问题的,只有当两者是共享变量时,才会有线程安全问题。主要的问题点在于多线程环境下,所有线程任何时刻都可对数组和链表进行操作,这会导致值被覆盖,甚至混乱的情况。如果有线程安全问题,在迭代的过程中,会频繁报
ConcurrentModificationException 的错误,意思是在我当前循环的过程中,数组或链表的结构被其它线程修改了。
如何解决线程安全问题?
Java 源 码 中 推 荐 使 用 Collections#synchronizedList 进 行 解 决 ,
Collections#synchronizedList 的返回值是 List 的每个方法都加了 synchronized
锁,保证了在同一时刻,数组和链表只会被一个线程所修改,或者采用CopyOnWriteArrayList 并发 List来解决,这个类我们后面会说

技术
©2019-2020 Toolsou All rights reserved,
LinkedHashMap基本用法&使用实现简单缓存 dedecms网站被黑 劫持到其他网站如何解决苹果不送充填器耳机真为环保?可能还是为了赚钱吧图片格式转换错误总结-myBatis plus 分页numpy:多维数组的创建用C语言做很简单的飞机游戏Keras保存与加载模型(JSON+HDF5)福布斯中国汽车富豪榜:何小鹏第11 李想第14 李斌第15hive大量小文件处理方法总结