ArrayList&&LinkedList 性能比较
最近在对比List下的两大功臣,功臣之一为ArrayList;功臣之二为LinkedList;
通过这次再次深入理解,有了如下的几点重新价值观刷新:
- 【插入】我们都知道因为ArrayList底层是数组实现的;LinkedList底层是链表实现的;所以对于新增数据而言,肯定是LinkedList性能远远高于ArrayList的性能;但实践结果并非如此,ArrayList的新增性能并不低,而且通过测试,其比LinkedList插入速度还快。(测试JDK版本 1.8)
- 【获取】由于LinkedList是链表结构,没有角标的概念,没有实现RandomAccess接口,不具备随机元素访问功能,所以在get方面表现的差强人意,ArrayList再一次完胜。具体为何LinkedList会这么慢呢?其实是因为LinkedList是链表结构,没有角标的概念,没有实现RandomAccess接口,不具备随机元素访问功能,所以在get方面表现的差强人意
- 【随机根据某个索引插入元素,到底谁快呢?】
操作代码如下:
//迭代次数
public static int ITERATION_NUM = 10000000;
public static void main(String[] agrs) {
insertPerformanceCompare();
}
//新增性能比较:
public static void insertPerformanceCompare() {
System.out.println("LinkedList新增测试开始");
long start = System.nanoTime();
List<Integer> linkedList = new LinkedList<Integer>();
for (int x = 0; x < ITERATION_NUM; x++) {
linkedList.add(x);
}
long end = System.nanoTime();
System.out.println("linkedList time one:"+(end - start));
long startInsert=System.nanoTime();
//依次执行,看执行时间
linkedList.add(0,11);
linkedList.add(10,11);
linkedList.add(100,11);
linkedList.add(1000,11);
linkedList.add(10000,11);
linkedList.add(100000,11);
linkedList.add(1000000,11);
long endInsert=System.nanoTime();
System.out.println("linkedList time two:"+(endInsert-startInsert));
System.out.println("ArrayList新增测试开始");
long startArray = System.nanoTime();
List<Integer> arrayList = new ArrayList<Integer>();
for (int x = 0; x < ITERATION_NUM; x++) {
arrayList.add(x);
}
long endArray = System.nanoTime();
System.out.println("arrayList time one:"+(endArray - startArray));
long startArrayInsert=System.nanoTime();
arrayList.add(0,11);
arrayList.add(10,11);
arrayList.add(100,11);
arrayList.add(1000,11);
arrayList.add(10000,11);
arrayList.add(100000,11);
arrayList.add(1000000,11);
long endArrayInsert=System.nanoTime();
System.out.println("arrayList time two:"+(endArrayInsert-startArrayInsert));
}
index insert | ArrayList | LinkedList |
---|---|---|
0 | 3646828 | 33657 |
10 | 3670657 | 33118 |
100 | 3628176 | 33256 |
1000 | 3270814 | 44075 |
10000 | 3696530 | 128725 |
100000 | 3656730 | 1010909 |
1000000 | 3606553 | 10099185 |
- 【随机删除某一个位置的元素,到底谁快呢?】
remove关键代码
linkedList.remove(0);
linkedList.remove(10);
linkedList.remove(100);
linkedList.remove(1000);
linkedList.remove(10000);
linkedList.remove(100000);
linkedList.remove(1000000);
arrayList.remove(0);
arrayList.remove(10);
arrayList.remove(100);
arrayList.remove(1000);
arrayList.remove(10000);
arrayList.remove(100000);
arrayList.remove(1000000);
index del | ArrayList | LinkedList |
---|---|---|
0 | 3319289 | 16816 |
10 | 3796653 | 17964 |
100 | 3462862 | 19898 |
1000 | 3474424 | 27497 |
10000 | 3320296 | 113838 |
100000 | 3312930 | 1803475 |
1000000 | 3029520 | 10050950 |
当看到如上数据时,不知道第一感是作何感受?其实当理解了其底层实现的时候,就不吃惊了。
通过如上数据可以发现,对于ArrayList而言,其不管是通过索引增加到哪个位置还是移除某个元素,其用的时间都是均等的;而对于LinkedList而言,则随着索引的增加用的时间逐渐增大。所以以上得到结论:
- void add(int index, E element) 当数据量超过6位数之后,则考虑使用ArrayList吧
- E remove(int index) 当数据量超过6位数之后,则考虑使用ArrayList吧
为何会出现这么大的差距呢?上述文章中我们曾提到过,对于ArrayList而言,因为其实现了RandomAccess,有了快速随机访问存储元素的功能,所以只要是通过索引的操作,其都是通过角标实现的,进而不用遍历整个集合,所以效率更高。