一般大家都知道ArrayList和LinkedList的大致区别:
     1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
     2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
     3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

ArrayList和LinkedList是两个集合类,用于存储一系列的对象引用(references)。例如我们可以用ArrayList来存储一系列的String或者Integer。那么ArrayList和LinkedList在性能上有什么差别呢?什么时候应该用ArrayList什么时候又该用LinkedList呢?

一.时间复杂度
首先一点关键的是,ArrayList的内部实现是基于基础的对象数组的,因此,它使用get方法访问列表中的任意一个元素时(random

access),它的速度要比LinkedList快。LinkedList中的get方法是按照顺序从列表的一端开始检查,直到另外一端。对LinkedList而言,访问列表中的某个指定元素没有更快的方法了。
假设我们有一个很大的列表,它里面的元素已经排好序了,这个列表可能是ArrayList类型的也可能是LinkedList类型的,现在我们对这个列表来进行二分查找(binary
search),比较列表是ArrayList和LinkedList时的查询速度,看下面的程序:

  1. package com.reyo.test;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. import java.util.Random;
  5. import java.util.ArrayList;
  6. import java.util.Arrays;
  7. import java.util.Collections;
  8. public class TestList ...{
  9. public static final int N=50000;
  10. public static List values;
  11. static...{
  12. Integer vals[]=new Integer[N];
  13. Random r=new Random();
  14. for(int i=0,currval=0;i<N;i++)...{
  15. vals=new Integer(currval);
  16. currval+=r.nextInt(100)+1;
  17. }
  18. values=Arrays.asList(vals);
  19. }
  20. static long timeList(List lst)...{
  21. long start=System.currentTimeMillis();
  22. for(int i=0;i<N;i++)...{
  23. int index=Collections.binarySearch(lst, values.get(i));
  24. if(index!=i)
  25. System.out.println("***错误***");
  26. }
  27. return System.currentTimeMillis()-start;
  28. }
  29. public static void main(String args[])...{
  30. System.out.println("ArrayList消耗时间:"+timeList(new ArrayList(values)));
  31. System.out.println("LinkedList消耗时间:"+timeList(new LinkedList(values)));
  32. }
  33. }

我得到的输出是:ArrayList消耗时间:15  LinkedList消耗时间:2596
这个结果不是固定的,但是基本上ArrayList的时间要明显小于LinkedList的时间。因此在这种情况下不宜用LinkedList。二分查找法使用的随机访问(random

access)策略,而LinkedList是不支持快速的随机访问的。对一个LinkedList做随机访问所消耗的时间与这个list的大小是成比例的。而相应的,在ArrayList中进行随机访问所消耗的时间是固定的。

这是否表明ArrayList总是比LinkedList性能要好呢?这并不一定,在某些情况下LinkedList的表现要优于ArrayList,有些算法在LinkedList中实现时效率更高。比方说,利用Collections.reverse方法对列表进行反转时,其性能就要好些。

看这样一个例子,加入我们有一个列表,要对其进行大量的插入和删除操作,在这种情况下LinkedList就是一个较好的选择。请看如下一个极端的例子,我们重复的在一个列表的开端插入一个元素:

  1. package com.mangocity.test;
  2. import java.util.*;
  3. public class ListDemo {
  4. static final int N=50000;
  5. static long timeList(List list){
  6. long start=System.currentTimeMillis();
  7. Object o = new Object();
  8. for(int i=0;i<N;i++)
  9. list.add(0, o);
  10. return System.currentTimeMillis()-start;
  11. }
  12. public static void main(String[] args) {
  13. System.out.println("ArrayList耗时:"+timeList(new ArrayList()));
  14. System.out.println("LinkedList耗时:"+timeList(new LinkedList()));
  15. }
  16. }

这时我的输出结果是:ArrayList耗时:2463 LinkedList耗时:15
这和前面一个例子的结果截然相反,当一个元素被加到ArrayList的最开端时,所有已经存在的元素都会后移,这就意味着数据移动和复制上的开销。相反的,将一个元素加到LinkedList的最开端只是简单的未这个元素分配一个记录,然后调整两个连接。在LinkedList的开端增加一个元素的开销是固定的,而在ArrayList的开端增加一个元素的开销是与ArrayList的大小成比例的。

二.空间复杂度
在LinkedList中有一个私有的内部类,定义如下:

  1. private static class Entry {
  2. Object element;
  3. Entry next;
  4. Entry previous;
  5. }

每个Entry对象reference列表中的一个元素,同时还有在LinkedList中它的上一个元素和下一个元素。一个有1000个元素的LinkedList对象将有1000个链接在一起的Entry对象,每个对象都对应于列表中的一个元素。这样的话,在一个LinkedList结构中将有一个很大的空间开销,因为它要存储这1000个Entity对象的相关信息。
ArrayList使用一个内置的数组来存储元素,这个数组的起始容量是10.当数组需要增长时,新的容量按如下公式获得:新容量=(旧容量*3)/2+1,也就是说每一次容量大概会增长50%。这就意味着,如果你有一个包含大量元素的ArrayList对象,那么最终将有很大的空间会被浪费掉,这个浪费是由ArrayList的工作方式本身造成的。如果没有足够的空间来存放新的元素,数组将不得不被重新进行分配以便能够增加新的元素。对数组进行重新分配,将会导致性能急剧下降。如果我们知道一个ArrayList将会有多少个元素,我们可以通过构造方法来指定容量。我们还可以通过trimToSize方法在ArrayList分配完毕之后去掉浪费掉的空间。

三.总结
ArrayList和LinkedList在性能上各有优缺点,都有各自所适用的地方,总的说来可以描述如下:
1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。
2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。
3.LinkedList不支持高效的随机元素访问。
4.ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间

可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。

java List集合记录 ArrayList和LinkedList的区别的更多相关文章

  1. Java自学-集合框架 ArrayList和LinkedList的区别

    ArrayList和LinkedList的区别 步骤 1 : ArrayList和LinkedList的区别 ArrayList ,插入,删除数据慢 LinkedList, 插入,删除数据快 Arra ...

  2. Java自学-集合框架 ArrayList和HashSet的区别

    Java ArrayList和HashSet的区别 示例 1 : 是否有顺序 ArrayList: 有顺序 HashSet: 无顺序 HashSet的具体顺序,既不是按照插入顺序,也不是按照hashc ...

  3. java中vector、ArrayList、LinkedList的区别

    转 首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList.Vector和LinkedList.List用于存放多个元素,能够维护元素的次序,并且允许元素的重复.3个 ...

  4. Java面试题之ArrayList和LinkedList的区别

    先看下类图: 相同点: 都实现了List接口和Collection: 不同点: 1.ArrayList是基于数组实现的:LinkedList是基于链表实现的: 2.ArrayList随机查询速度快:L ...

  5. java集合框架05——ArrayList和LinkedList的区别

    前面已经学习完了List部分的源码,主要是ArrayList和LinkedList两部分内容,这一节主要总结下List部分的内容. List概括 先来回顾一下List在Collection中的的框架图 ...

  6. java集合框架之ArrayList与LinkedList的区别

    参考http://how2j.cn/k/collection/collection-arraylist-vs-linkedlist/690.html#nowhere ArrayList和LinkedL ...

  7. JAVA集合一:ArrayList和LinkedList

    JAVA集合一:ArrayList和LinkedList 参考链接: HOW2J.CN 前言 这几篇博客重点记录JAVA的几个重要的集合框架:ArrayList.LinkedList.HashMap. ...

  8. Java中ArrayList与LinkedList的区别

    Java中ArrayList与LinkedList的区别 一般大家都知道ArrayList和LinkedList的区别: 1. ArrayList的实现是基于数组,LinkedList的实现是基于双向 ...

  9. Java进阶(十七)ArrayList与LinkedList的区别

    ArrayList与LinkedList的区别 ArrayList ArrayList其实是包装了一个数组 Object[],当实例化一个ArrayList时,一个数组也被实例化,当向ArrayLis ...

随机推荐

  1. SqlServer共用表达式(CTE)With As

    共用表表达式(CTE)可以看成是一个临时的结果集,可以再SELECT,INSERT,UPDATE,DELETE,MARGE语句中多次引用. 一好处:使用共用表表达式可以让语句更加清晰简练. 1.可以定 ...

  2. 6. 缓存 - 《APS.NET本质论》

    CaChe是ASP.NET中唯一可以根据服务器使用情况,动态管理内存使用的状态管理方案.我们通过每个缓存数据的键值字符串来区分缓存的数据. 简单案例来说.将数据从数据库/文件取出放在服务器内存中,后来 ...

  3. 高能天气——团队Scrum冲刺阶段-Day 6

    高能天气--团队Scrum冲刺阶段-Day 6 今日完成任务 于欣月:完善计步器功能:实现了历史步数统计和设置锻炼计划功能,并实现可视化图形界面 余坤澎:将闹钟部分和小游戏部分进行了合并 康皓越:配合 ...

  4. 014.Zabbix的Agent key

    一 常见key 1.1 监控网卡流量的key net.if.{in/out}[if,<mode>] if表示网卡接口,mode表示取值类型. mode参数:bytes(默认),packet ...

  5. MIT-6.828-JOS-lab2:Memory management

    MIT-6.828 Lab 2: Memory Management实验报告 tags:mit-6.828 os 概述 本文主要介绍lab2,讲的是操作系统内存管理,从内容上分为三部分: 第一部分讲的 ...

  6. InnoDB的锁机制浅析(五)—死锁场景(Insert死锁)

    可能的死锁场景 文章总共分为五个部分: InnoDB的锁机制浅析(一)-基本概念/兼容矩阵 InnoDB的锁机制浅析(二)-探索InnoDB中的锁(Record锁/Gap锁/Next-key锁/插入意 ...

  7. Kali Linux 2017.3发布了

     Kali Linux 2017.3发布了 Kali Linux官方在11月21日发布Kali Linux 2017的第三个版本2017.3.这次发布变化相对不大,主要是设置面板风格发生改变,增加少量 ...

  8. android listview 优化

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha android convertview作用 ======= 1,convertView复 ...

  9. BZOJ.3004.[SDOI2012]吊灯(结论)

    题目链接 BZOJ 洛谷 题意: 将树划分为k个连通块,要求每个连通块大小相同.输出可能的大小. 结论: 满足条件时颜色的连通块数为k,当且仅当有 \(n/k\) 个节点满足它的子树是k的倍数(显然还 ...

  10. Educational Codeforces Round 14 C. Exponential notation 数字转科学计数法

    C. Exponential notation 题目连接: http://www.codeforces.com/contest/691/problem/C Description You are gi ...