<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問 http://qaseven.github.io/

    Java中ArrayList和LinkedList區(qū)別

    一般大家都知道ArrayList和LinkedList的大致區(qū)別:
      1.ArrayList是實(shí)現(xiàn)了基于動(dòng)態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)。
      2.對(duì)于隨機(jī)訪問get和set,ArrayList覺得優(yōu)于LinkedList,因?yàn)長(zhǎng)inkedList要移動(dòng)指針。
      3.對(duì)于新增和刪除操作add和remove,LinedList比較占優(yōu)勢(shì),因?yàn)锳rrayList要移動(dòng)數(shù)據(jù)。
      ArrayList和LinkedList是兩個(gè)集合類,用于存儲(chǔ)一系列的對(duì)象引用(references)。例如我們可以用ArrayList來存儲(chǔ)一系列的String或者Integer。那么ArrayList和LinkedList在性能上有什么差別呢?什么時(shí)候應(yīng)該用ArrayList什么時(shí)候又該用LinkedList呢?
      一.時(shí)間復(fù)雜度
      首先一點(diǎn)關(guān)鍵的是,ArrayList的內(nèi)部實(shí)現(xiàn)是基于基礎(chǔ)的對(duì)象數(shù)組的,因此,它使用get方法訪問列表中的任意一個(gè)元素時(shí)(random access),它的速度要比LinkedList快。LinkedList中的get方法是按照順序從列表的一端開始檢查,直到另外一端。對(duì)LinkedList而言,訪問列表中的某個(gè)指定元素沒有更快的方法了。
      假設(shè)我們有一個(gè)很大的列表,它里面的元素已經(jīng)排好序了,這個(gè)列表可能是ArrayList類型的也可能是LinkedList類型的,現(xiàn)在我們對(duì)這個(gè)列表來進(jìn)行二分查找(binary search),比較列表是ArrayList和LinkedList時(shí)的查詢速度,看下面的程序:
    package testlist;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Random;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    public class TestList {
    public static final int N = 50000;
    public static List<Integer> values;
    static {
    Integer vals[] = new Integer[N];
    Random r = new Random();
    for (int i = 0, currval = 0; i < N; i++) {
    vals[i] = new Integer(currval);
    currval += r.nextInt(100) + 1;
    }
    values = Arrays.asList(vals);
    }
    static long timeList(List<Integer> lst) {
    long start = System.currentTimeMillis();
    for (int i = 0; i < N; i++) {
    int index = Collections.binarySearch(lst, values.get(i));
    if (index != i)
    System.out.println("***錯(cuò)誤***");
    }
    return System.currentTimeMillis() - start;
    }
    public static void main(String args[]) {
    System.out.println("ArrayList消耗時(shí)間:" + timeList(new ArrayList<Integer>(values)));
    System.out.println("LinkedList消耗時(shí)間:" + timeList(new LinkedList<Integer>(values)));
    }
    }
      我得到的輸出是:
      ArrayList消耗時(shí)間:31
      LinkedList消耗時(shí)間:30688
     這個(gè)結(jié)果不是固定的,但是基本上ArrayList的時(shí)間要明顯小于LinkedList的時(shí)間。因此在這種情況下不宜用LinkedList。二分查找法使用的隨機(jī)訪問(random access)策略,而LinkedList是不支持快速的隨機(jī)訪問的。對(duì)一個(gè)LinkedList做隨機(jī)訪問所消耗的時(shí)間與這個(gè)list的大小是成比例的。而相應(yīng)的,在ArrayList中進(jìn)行隨機(jī)訪問所消耗的時(shí)間是固定的。
      如果只是遍歷一下:
    packagetestlist;
    importjava.util.LinkedList;
    importjava.util.List;
    importjava.util.Random;
    importjava.util.ArrayList;
    importjava.util.Arrays;
    publicclassTestList{
    publicstaticfinalintN=50000;
    publicstaticList<Integer>values;
    static{
    Integervals[]=newInteger[N];
    Randomr=newRandom();
    for(inti=0,currval=0;i<N;i++){
    vals[i]=newInteger(currval);
    currval+=r.nextInt(100)+1;
    }
    values=Arrays.asList(vals);
    }
    staticlongtimeList(List<Integer>lst){
    longstart=System.currentTimeMillis();
    for(inti=0;i<lst.size();i++){
    lst.get(i);
    }
    returnSystem.currentTimeMillis()-start;
    }
    publicstaticvoidmain(Stringargs[]){
    System.out.println("ArrayList消耗時(shí)間:"+timeList(newArrayList<Integer>(values)));
    System.out.println("LinkedList消耗時(shí)間:"+timeList(newLinkedList<Integer>(values)));
    }
    }
      輸出:
      ArrayList消耗時(shí)間:0
      LinkedList消耗時(shí)間:1703
      這是否表明ArrayList總是比LinkedList性能要好呢?這并不一定,在某些情況下LinkedList的表現(xiàn)要優(yōu)于ArrayList,有些算法在LinkedList中實(shí)現(xiàn)時(shí)效率更高。比方說,利用Collections.reverse方法對(duì)列表進(jìn)行反轉(zhuǎn)時(shí),其性能就要好些。
      看這樣一個(gè)例子,加入我們有一個(gè)列表,要對(duì)其進(jìn)行大量的插入和刪除操作,在這種情況下LinkedList就是一個(gè)較好的選擇。請(qǐng)看如下一個(gè)極端的例子,我們重復(fù)的在一個(gè)列表的開端插入一個(gè)元素:
    package testlist;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    public class ListDemo {
    static final int N = 50000;
    static long timeList(List<Object> list) {
    long start = System.currentTimeMillis();
    Object o = new Object();
    for (int i = 0; i < N; i++)
    list.add(0, o);
    return System.currentTimeMillis() - start;
    }
    public static void main(String[] args) {
    System.out.println("ArrayList耗時(shí):" + timeList(new ArrayList<Object>()));
    System.out.println("LinkedList耗時(shí):" + timeList(new LinkedList<Object>()));
    }
    }
      這時(shí)我的輸出結(jié)果是:
      ArrayList耗時(shí):1813
      LinkedList耗時(shí):0
      這和前面一個(gè)例子的結(jié)果截然相反,當(dāng)一個(gè)元素被加到ArrayList的最開端時(shí),所有已經(jīng)存在的元素都會(huì)后移,這就意味著數(shù)據(jù)移動(dòng)和復(fù)制上的開銷。相反的,將一個(gè)元素加到LinkedList的最開端只是簡(jiǎn)單的未這個(gè)元素分配一個(gè)記錄,然后調(diào)整兩個(gè)連接。在LinkedList的開端增加一個(gè)元素的開銷是固定的,而在ArrayList的開端增加一個(gè)元素的開銷是與ArrayList的大小成比例的。

      二.空間復(fù)雜度
      在LinkedList中有一個(gè)私有的內(nèi)部類,定義如下:
    private static class Entry<E> {
    E element;
    Entry<E> next;
    Entry<E> previous;
    Entry(E element, Entry<E> next, Entry<E> previous) {
    this.element = element;
    this.next = next;
    this.previous = previous;
    }
    }
      每個(gè)Entry對(duì)象reference列表中的一個(gè)元素,同時(shí)還有在LinkedList中它的上一個(gè)元素和下一個(gè)元素。一個(gè)有1000個(gè)元素的LinkedList對(duì)象將有1000個(gè)鏈接在一起的Entry對(duì)象,每個(gè)對(duì)象都對(duì)應(yīng)于列表中的一個(gè)元素。這樣的話,在一個(gè)LinkedList結(jié)構(gòu)中將有一個(gè)很大的空間開銷,因?yàn)樗鎯?chǔ)這1000個(gè)Entity對(duì)象的相關(guān)信息。
      ArrayList使用一個(gè)內(nèi)置的數(shù)組來存儲(chǔ)元素,這個(gè)數(shù)組的起始容量是10.當(dāng)數(shù)組需要增長(zhǎng)時(shí),新的容量按如下公式獲得:新容量=(舊容量*3)/2+1,也就是說每一次容量大概會(huì)增長(zhǎng)50%。這就意味著,如果你有一個(gè)包含大量元素的ArrayList對(duì)象,那么最終將有很大的空間會(huì)被浪費(fèi)掉,這個(gè)浪費(fèi)是由ArrayList的工作方式本身造成的。如果沒有足夠的空間來存放新的元素,數(shù)組將不得不被重新進(jìn)行分配以便能夠增加新的元素。對(duì)數(shù)組進(jìn)行重新分配,將會(huì)導(dǎo)致性能急劇下降。如果我們知道一個(gè)ArrayList將會(huì)有多少個(gè)元素,我們可以通過構(gòu)造方法來指定容量。我們還可以通過trimToSize方法在ArrayList分配完畢之后去掉浪費(fèi)掉的空間。
      三.總結(jié)
      ArrayList和LinkedList在性能上各有優(yōu)缺點(diǎn),都有各自所適用的地方,總的說來可以描述如下:
      1.對(duì)ArrayList和LinkedList而言,在列表末尾增加一個(gè)元素所花的開銷都是固定的。對(duì)ArrayList而言,主要是在內(nèi)部數(shù)組中增加一項(xiàng),指向所添加的元素,偶爾可能會(huì)導(dǎo)致對(duì)數(shù)組重新進(jìn)行分配;而對(duì)LinkedList而言,這個(gè)開銷是統(tǒng)一的,分配一個(gè)內(nèi)部Entry對(duì)象。
      2.在ArrayList的中間插入或刪除一個(gè)元素意味著這個(gè)列表中剩余的元素都會(huì)被移動(dòng);而在LinkedList的中間插入或刪除一個(gè)元素的開銷是固定的。
      3.LinkedList不支持高效的隨機(jī)元素訪問。
      4.ArrayList的空間浪費(fèi)主要體現(xiàn)在在list列表的結(jié)尾預(yù)留一定的容量空間,而LinkedList的空間花費(fèi)則體現(xiàn)在它的每一個(gè)元素都需要消耗相當(dāng)?shù)目臻g
      可以這樣說:當(dāng)操作是在一列數(shù)據(jù)的后面添加數(shù)據(jù)而不是在前面或中間,并且需要隨機(jī)地訪問其中的元素時(shí),使用ArrayList會(huì)提供比較好的性能;當(dāng)你的操作是在一列數(shù)據(jù)的前面或中間添加或刪除數(shù)據(jù),并且按照順序訪問其中的元素時(shí),就應(yīng)該使用LinkedList了。

    posted on 2014-01-08 10:41 順其自然EVO 閱讀(199) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    <2014年1月>
    2930311234
    567891011
    12131415161718
    19202122232425
    2627282930311
    2345678

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲五月综合缴情在线观看| 国产亚洲精品美女久久久久久下载| 亚洲av午夜成人片精品电影| 中国人xxxxx69免费视频| 亚洲一区二区三区免费| 亚洲中文无码mv| 亚洲成人免费网站| 欧洲亚洲国产清在高| 亚洲国产一成久久精品国产成人综合| 亚洲电影免费观看| 国产三级在线免费| 国产精品黄页免费高清在线观看| 亚洲色成人网站WWW永久四虎| 亚洲综合亚洲国产尤物| 久久精品国产精品亚洲艾| 亚洲精品国产高清不卡在线| 日美韩电影免费看| 成人毛片免费观看视频在线| 99久久99久久精品免费看蜜桃| 一级毛片免费观看不卡视频| 免费在线中文日本| 野花香高清视频在线观看免费| 亚洲一区二区三区免费| 特级毛片爽www免费版| 亚洲AV无码专区在线观看成人 | 高清免费久久午夜精品| 免费激情网站国产高清第一页 | 日韩精品免费一区二区三区| 国产精品无码免费播放| 美女视频黄的全免费视频 | 亚洲自国产拍揄拍| 亚洲伊人久久大香线蕉啊| 亚洲第一页在线视频| 亚洲理论在线观看| 亚洲国产精品久久丫| 亚洲国产日韩在线一区| 亚洲高清一区二区三区| 亚洲 暴爽 AV人人爽日日碰| 亚洲国产精品成人午夜在线观看 | 99久热只有精品视频免费观看17| 十八禁视频在线观看免费无码无遮挡骂过 |