从最基本的 ArrayList 谈起
你的时间有限,不要浪费于重复别人的生活。不要让别人的观点淹没了你内心的声音。
——乔布斯
小a昨晚看了一宿ArrayList的源码,准备接受今天的模拟面试,中午吃完饭后,就开始催促大Q,赶紧开始今天的面试吧!
打开牛客网,进入在线视频面试,等待双方上线中...
Q:那你简单介绍下ArrayList吧
小a心想,看来万变不离其宗,介绍一个组件,最科学权威的回答就是 JDK 中 API 的类注释了.
List接口的可调整大小的数组实现。实现所有可选的列表操作,并允许所有元素,包括null。除了实现List接口之外,此类还提供一些方法来操纵内部用于存储列表的数组的大小。此类与Vector大致等效,但它非线程安全.
- size
- isEmpty
- get
- set
等操作均是在常量时间开销。add 操作以固定的常量时间运行,即添加n个元素需要O(n)的时间。所有其他操作均大致以线性时间运行。与LinkedList实现相比,常数因子较低。
每个ArrayList实例都有一个容量 capacity。用做在列表中存储元素的数组的大小。它至少与列表大小一样大。随着元素添加到ArrayList中,其容量会自动增长。
应用程序可以使用ensureCapacity操作在添加大量元素之前增加ArrayList实例的容量。这可以减少增量重新分配的数量。
值得注意的是,ArrayList是非同步的。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改列表,则必须在外部进行同步。这通常是通过对自然封装了对象的某些对象进行同步来实现的list。如果不存在这样的对象,则应使用Collections.synchronizedList方法“包装”列表。原理同Vector是一样的,就是给所有的方法套上一层synchronized。最好在创建时就完成此操作,以防止意外的不同步访问列表:
List list = Collections.synchronizedList(new ArrayList(...));
此类的迭代器和listIterator方法返回的迭代器是快速失败(fail-fast)的.
此类是Java Collections Framework的成员。
Q:你刚才提到说结构修改,指的是哪些操作呢?
a:结构修改是添加或删除一个或多个元素或显式调整后备数组大小的任何操作;仅设置元素的值不属于结构修改
ArrayList允许放置 null,动态数组自动扩容,get、set等时间复杂度都是 O (1),且非线程安全,并发环境下推荐使用线程安全类 - Collections#synchronizedList,使用增强 for 循环或迭代器迭代过程中,如果数组大小被改变,会快速失败,抛异常.
Q:说说快速失败是什么?
> 还好在类注释里也已经解释了这个机制,不然我又要开始胡说了
a:如果在创建迭代器之后的任何时间以任何方式对列表进行了结构修改,则除了通过迭代器自己的remove或add方法之外,迭代器都会抛出ConcurrentModificationException。因此,面对并发修改,迭代器会快速且干净地失败,而不会在未来的不确定时间内冒任意不确定的行为的风险。
不过注意,迭代器的快速失败行为无法得到保证,因为通常来说,在存在非同步的并发修改的情况下,不可能做出任何严格的保证。快速失败的迭代器会尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序的正确性是错误的:迭代器的快速失败行为仅应用于检测错误。
Q:ArrayList的默认初始容量大小多少?
> 怎么会问这么简单问题,一定有诈!印象中怎么感觉好像是 10?
小a灵机一动,感觉此事绝不简单.
> 我记得昨晚看了源码好像不是这样的,我得好好整理下思绪,拿下这题!
-
存储ArrayList的元素的数组缓冲区。ArrayList的容量是此数组缓冲区的长度。添加第一个元素时,任何具有 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
<p> “挨踢”业行情日益严峻,企业招聘门槛愈来愈高,大厂hc更是少之又少,而Java技术面试普遍对基础知识的掌握考察特别深,大多数同学突击所看的 Java 面试基础知识点根本达不到面试官近乎挑剔的要求。 本专刊针对如今的校招及社招痛点,深入解析 JDK 的核心源码,探究 JDK 的设计精髓及最佳实践,同时以模拟面试的场景切入,让同学们在阅读过程中也能轻松掌握面试技巧。 本专刊购买后即可解锁所有章节,故不可以退换哦~ </p>

查看20道真题和解析