每日一面系列之ArrayList夺命连环问

1.ArrayList用过吗?知道是干什么的吗?有什么特点?

ArrayList是用来存储数据的一个集合,当我们存储的数据类型是基本数据类型的时候,需要存储他们的包装类。ArrayList底层是Object数组实现的。它的特点是查询效率高(根据元素下表可以直接访问),增删效率低(增删元素需要对其他元素位置进行移动),线程不安全,使用频率比较高。

2.为什么ArrayList线程不安全还要用?

因为在日常的开发中,我们使用集合大多数情况是去做一些查询,不会频繁的进行增删操作。如果需要做一些频繁的增删操作可以使用LinkedList,因为它底层是使用双向链表,所以增删效率比较高。如果需要线程安全的集合,那么可以使用Vector,因为它的方法基本都是用了synchronized进行加锁。目前还不存在一个完美的集合,查询效率高,增删效率也高而且还线程安全,这也是数据结构的特性所致,不能做到兼顾,只能找一个相对平衡的点,没有绝对的好坏,具体使用情况还要看需求而定。

3.ArrayList底层是数组实现的,但是数组的长度大小是固定的,如果不断的向里面添加元素,会有什么问题?

ArrayList可以通过构造方法初始化底层数组的大小。

通过无参构造方法创建的ArrayList底层数组默认大小为空,会定义一个空的数组,直到通过add()方法添加元素的时候,才会为数组分配默认初始容量,大小为10(DEFAULT_CAPACITY = 10)。如果是通过有参构造创建的ArrayList,底层数组大小初始值为指定大小。

4.数组长度的大小是固定的,而ArrayList中却可以存放任意数量的元素,它是怎么实现的(扩容机制)?

因为采用无参构造方法创建的ArrayList底层数组大小默认为10,所以这里我们就以数组大小10为例,当我们新增元素的时候发现数组已经满了,此时它会重新定义一个大小为10+10/2(增加原来的0.5倍 ),如果是使用有参构造方法创建的,扩容也会根据指定大小进行扩容,规则是一样的。

5.说一下ArrayList在1.7版本之前和之后初始化有什么区别?

JDK1.7之前初始化时会调用this(10),是真正的初始化为10,从1.7版本开始首先会默认初始化一个空的数组,直到调用add()方法添加元素的时候才会将数组初始化大小变为10。

6.为什么ArrayList底层数组默认初始化大小是10?

Sun公司的开发人员通过对大量程序代码进行调研,发现10这个长度是最常用也是最有效率的,其实8、12等都可以。10看起来可能比较舒服吧!

7.你说ArrayList新增元素比较慢,为什么慢?新增元素的一个具体流程是什么样的?

在新增元素的时候,首先会对数组长度进行校验,看是否需要扩容。之后就是复制数组中的元素,比如现在要在下标为5的位置添加一个元素,那么它会将从下标为5的元素开始对元素进行复制,整体往后移动一位,然后将新元素添加到下标5的位置。下面以图解方式说明一下:

原数组目前是这样的:
在这里插入图片描述
如果要往下标为5的位置添加一个新的元素,是这样的:
在这里插入图片描述
然后将新元素插入下标为5的位置,是这样的:
在这里插入图片描述
至于它插入为什么慢,试想一下如果现在有成千上万个元素,是不是你添加元素的下标位置开始往后的元素都要进行复制、移位?如果再需要扩容的话,那效率肯定会更慢。

8.ArrayList的插入删除一定很慢吗?

这取决于你插入或者删除的元素的下标距离数组末端有多远,ArrayList拿来作为堆栈来用还是挺合适的,push和pop操作完全不涉及数据移动操作。

9.ArrayList中的删除操作流程是怎么样的?

删除和新增其实是一样的,只是叫法不同而已,操作流程是一样的,都会根据操作元素的下标位置对元素进行复制。

比如现在我们要删除下标为5的这个元素:
在这里插入图片描述
它会将下标为6开始的元素进行复制,然后往前移动,替换原来下标为5的元素:
在这里插入图片描述
所谓的删除操作,其实就是覆盖你所需要删除的下标位置的元素。

10.如果我不想用Vertor,又想让线程安全,怎么办?

用Collections.synchronizedList把一个普通ArrayList包装成一个线程安全版本的数组容器也可以,原理同Vector是一样的,就是给所有的方法套上一层synchronized。

11.ArrayList适合用来做队列吗?

我们都知道队列的特点就是先进先出(FIFO),如果要让ArrayList做到这样,那么插入元素和删除元素,必须一个操作从头部开始,一个操作从尾部开始。但是ArrayList插入和删除操作都会牵扯到数据的移动迁移,这个是非常消耗性能的,效率还很低,所以它不适合做队列。

12.比较一下ArrayList和LinkedList的遍历效率。

就单论遍历效率的话,ArrayList的效率肯定是高于LinkedList的。因为ArrayList遍历最大的优势就是在于内存的连续性,CPU的内部缓存结构会缓存连续的内存片段,可以大幅度降低读取内存的性能开销。

13.你对未来的职业规划是什么样的?

往专业方向靠拢,比如未来几年发展成技术负责人,带团队,多少年之后成为架构师,比较喜欢看一些技术类书籍来提升自己的能力等等。总之要让HR觉得你这个人很上进还很好学!

每日面试小练习,日后面试大轻松!

猜你喜欢

转载自blog.csdn.net/w1453114339/article/details/106969014