List是封装了针对线性表操作的接口,ArrayList和LinkedList是在项目里用的比较多的两个实现类。我在面试时一般会问,它们两者有什么差别?很多人能回答说,ArrayList是基于数组实现,而LinkedList是基于双向链表实现。
学过数据结构的同学都知道,如果我们要查找数组里的某个元素,可以根据如下的公式很快地定位到该元素的位置。
第i号元素的位置 = 第0号元素的位置+(i-1)*每个元素的长度。
但数组不擅长添加和删除元素,比如要在长度是10000的数组里的500号位置添加一个元素,我们首先得让500到10000号元素都往后移动一位,先把500号位置腾出来,随后再添加。删除也是类似。
和数组相对应,链表比较擅长添加和删除元素(只需要更改其中一个元素的指针即可),但不擅长于定位(如果要找500号元素,就得从0号开始一个个找)。
这种说法应付面试尚可,但在实际项目里,往往没有单纯的添加(或删除)和单纯的查找操作,一般是两者配合使用。比如我们会在一个for循环里通过add方法从头开始在尾部添加元素,完成后在另个地方通过get方法从头开始获取元素,这两个动作往往会配对出现
那么在这种情况下,该选用哪种集合?下面我们来通过ListCompare.java来比较一下这两类List的各种性能,从而来归纳它们的使用场景。
1 //省略必要的import集合包的代码
2 public class ListCompare {
3 //在尾部添加元素
4 static void testAddatTail(List list,String type) {
5 int size = 1000000;
6 long start=System.currentTimeMillis();
7 //通过for循环在尾部添加元数据
8 for(int i = 0;i
在下表3.1里,我们列出了在上述代码里定义的方法。
表3.1 针对两种不同集合对比测试方法归纳表
方法名 |
行数 |
动作 |
testAddatTail |
第4到14行 |
通过for循环在尾部添加1000000个元素 |
testRandomSearch |
第16到25行 |
从集合的随机位置拿元素,相当于随机查找 |
testAddatRandom |
第27到35行 |
在集合的随机位置添加元素 |
在main函数的39和40行,我们定义了两种List,随后从42到47行,我们分别针对两种不同的List集合执行了对比测试方法,如果我们运行多次,输出的时间未必都相等,但从中我们能看到两者的对比,根据其中的一次运行结果,我们能整理出如下表3.2所示的结论。
表3.2 运行结果分析表
比较项 |
集合种类 |
运行时间 |
分析 |
在尾部添加 |
ArrayList |
141 |
ArrayList是基于数组,和基于链表的ListedList相比,能很快地定位到尾部 |
LinkedList |
219 |
||
在随机位置添加 |
ArrayList |
938 |
这里包含查找位置和添加两个动作,查找时基于数组的ArrayList占优,添加时基于LinkedList占优,综合下来还是LinkedList占优 |
LinkedList |
672 |
||
在随机位置查找 |
ArrayList |
4109 |
基于数组的ArrayList很占优,相比基于链表的Linkedlist就需要消耗一定的代价了。 |
LinkedList |
5828 |
也就是说,如果被问到这类问题,你可以说出如下的结论。
第一,如果我们就一次性地通过add从集合尾部添加元素,添加完成后我们也只需读取一次,那么建议使用ArrayList,因为从上表来看,它两个动作的运行时间总和要小于LinketList。
第二,如果要频繁地添加元素,或者在完成添加元素后会频繁地通过indexOf方法从集合里查找元素,可以使用LinketList,理由是它的随机添加和随机查找的总时间消耗要小于ArrayList。
第三,请记得,如果在代码里indexOf的操作过于频繁从而成为项目运行的瓶颈时,可以考虑后文里提到的HashMap对象。
此外,ArrayList和Linkedlist都是线程不安全的,别把这点说成是它们的差别。
关于集合类的面试文章汇总:
Java集合方面的面试题:Set集合是如何判断重复
Java集合方面的面试题:对比ArrayList和Vector对象,分析Vector为什么不常用
Java集合方面的面试题:ArrayList和LinkedList有什么差别?分别适用于哪些场景?
Java集合方面的面试题:TreeSet、HashSet和LinkedHashSet的各自特点
Java集合方面的面试题:泛型的继承和通配符
Java集合方面的面试题大汇总
这是我的公众号,其中包含了大量面试文章,同时我自己出了多本Python和Java方面的书籍,会定期在公众号里发书的电子版。请大家关注下我的公众号,谢谢了。