关于ArrayList的5道面试题
以面试官视角看过不少 Java 面试后,下面 5 道 ArrayList 题最容易让初中级同学含糊过去。答清楚,分数会好看很多。
一、ArrayList 的大小如何自动增加?
这是最有技巧的一题,多数人答不上细节。往 ArrayList 里 add 时,Java 会检查现有数组够不够装新对象。不够就新建更长的数组,用 Arrays.copyOf 把旧数据拷过去,再让 elementData 指向新数组。
代码摘自 GrepCode.com 中的 Java ArrayList Code(OpenJDK 6):
注意三件事:新建数组;旧对象拷到新数组;现有引用改指向新数组。扩容公式在 JDK 6 是 (oldCapacity * 3)/2 + 1。
二、什么时候用 ArrayList,什么时候用 LinkedList?
访问比插入/删除更频繁时用 ArrayList;在某个下标频繁插入删除、或几乎不随机访问时用 LinkedList。
原因:ArrayList 按下标访问最坏是 O(1),LinkedList 可能是 O(n)。ArrayList 增删通常要 System.arraycopy,很吃资源,所以频繁插入删除时 LinkedList 更好。
| 场景 | 更合适 | 原因 |
|---|---|---|
| 按下标读、遍历多 | ArrayList |
数组随机访问 O(1) |
| 中间频繁增删 | LinkedList |
改指针,避免整段 arraycopy |
| 几乎只当队列头尾操作 | LinkedList / 队列实现 |
不需要按下标跳 |
三、把 ArrayList 传入或返回时,何时有安全隐患?
数组(同样适用于可变的 ArrayList 引用)若未经拷贝就直接赋给成员变量,调用方之后改原始数据,方法内部看到的那份也会变。下面是违规与修复。
ArrayList 被直接赋给成员变量——安全隐患:

修复这个安全隐患(先拷贝再保存):

四、如何把某个 ArrayList 复制到另一个?
几种做法:
-
使用 clone(),例如ArrayList newArray = oldArray.clone(); -
使用 ArrayList 构造方法,例如 ArrayList myObject = new ArrayList(myTempObject); -
使用 Collection 的 copy 方法。
注意 1 和 2 是浅拷贝(shallow copy)。
五、按下标增删对象时发生了什么?很慢吗?
增删要调用 System.arraycopy,效率低。需要频繁插入删除时换 LinkedList 等集合。
在某个索引 i 处添加元素:

删除某个索引 i 处的元素:

原文链接:vitalflux 翻译:ImportNew.com – kobekillerjun
译文链接:http://www.importnew.com/9928.html
一句话总结:ArrayList 靠数组扩容(JDK6 约 1.5 倍)和 arraycopy 搬家;随机访问快、中间增删慢,对外暴露前要拷贝,clone/构造都是浅拷贝。
转载请注明来源:关于ArrayList的5道面试题








