ArrayList和LinkedList各自實現(xiàn)和區(qū)別

轉(zhuǎn)自:(http://www.cnblogs.com/Alan-Jones/p/6426994.html)

ArrayList,LinkedList,Vestor這三個類都實現(xiàn)了java.util.List接口,但它們有各自不同的特性汁掠,主要如下:

一守屉、同步性

ArrayList,LinkedList是不同步的拆内,而Vestor是同步的血淌。所以如果不要求線程安全的話,可以使用ArrayList或LinkedList赦邻,可以節(jié)省為同步而耗費的開銷囚玫。但在多線程的情況下,有時候就不得不使用Vector了昨忆。當然丁频,也可以通過一些辦法包裝ArrayList,LinkedList,使他們也達到同步邑贴,但效率可能會有所降低席里。

二、數(shù)據(jù)增長
從內(nèi)部實現(xiàn)機制來講ArrayList和Vector都是使用Objec的數(shù)組形式來存儲的拢驾。當你向這兩種類型中增加元素的時候奖磁,如果元素的數(shù)目超出了內(nèi)部數(shù)組目前的長度它們都需要擴展內(nèi)部數(shù)組的長度,Vector缺省情況下自動增長原來一倍的數(shù)組長度繁疤,ArrayList是原來的50%,所以最后你獲得的這個集合所占的空間總是比你實際需要的要大咖为。所以如果你要在集合中保存大量的數(shù)據(jù)那么使用Vector有一些優(yōu)勢秕狰,因為你可以通過設(shè)置集合的初始化大小來避免不必要的資源開銷。

三躁染、檢索鸣哀、插入、刪除對象的效率

ArrayList和Vector中吞彤,從指定的位置(用index)檢索一個對象我衬,或在集合的末尾插入、刪除一個對象的時間是一樣的饰恕,可表示為O(1)挠羔。但是,如果在集合的其他位置增加或移除元素那么花費的時間會呈線形增長:O(n-i)埋嵌,其中n代表集合中元素的個數(shù)破加,i代表元素增加或移除元素的索引位置。為什么會這樣呢莉恼?以為在進行上述操作的時候集合中第i和第i個元素之后的所有元素都要執(zhí)行(n-i)個對象的位移操作拌喉。
LinkedList中,在插入俐银、刪除集合中任何位置的元素所花費的時間都是一樣的—O(1)尿背,但它在索引一個元素的時候比較慢,為O(i),其中i是索引的位置捶惜。
————————————————————————————————————————
一般大家都知道ArrayList和LinkedList的大致區(qū)別:
1.ArrayList是實現(xiàn)了基于動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu)田藐,LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)。
2.對于隨機訪問get和set吱七,ArrayList覺得優(yōu)于LinkedList汽久,因為LinkedList要移動指針。
3.對于新增和刪除操作add和remove踊餐,LinedList比較占優(yōu)勢景醇,因為ArrayList要移動數(shù)據(jù)。

ArrayList和LinkedList是兩個集合 類吝岭,用于存儲一系列的對象引用(references)三痰。例如我們可以用ArrayList來存儲一系列的String或者Integer。那么 ArrayList和LinkedList在性能上有什么差別呢窜管?什么時候應(yīng)該用ArrayList什么時候又該用LinkedList呢散劫?

一.時間復(fù) 雜度
首先一點關(guān)鍵的是,ArrayList的內(nèi)部實現(xiàn)是基于基礎(chǔ)的對象數(shù)組的幕帆,因此获搏,它使用get方法訪問列表中的任意一個元素時 (random access),它的速度要比LinkedList快失乾。LinkedList中的get方法是按照順序從列表的一端開始檢查常熙,直到另外一端纬乍。對 LinkedList而言,訪問列表中的某個指定元素沒有更快的方法了症概。
假設(shè)我們有一個很大的列表蕾额,它里面的元素已經(jīng)排好序了,這個列表可能是ArrayList類型 的也可能是LinkedList類型的彼城,現(xiàn)在我們對這個列表來進行二分查找(binary search),比較列表是ArrayList和LinkedList時的查詢速度退个,看下面的程序:

Java代碼
package com.mangocity.test;
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 values;   

 static...{   
     Integer vals[]=new Integer[N];   

     Random r=new Random();   

     for(int i=0,currval=0;i<N;i++)...{   
         vals=new Integer(currval);   
         currval+=r.nextInt(100)+1;   
     }   

     values=Arrays.asList(vals);   
 }   

 static long timeList(List 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("***錯誤***");   
     }   
     return System.currentTimeMillis()-start;   
 }   
 public static void main(String args[])...{   
     System.out.println("ArrayList消耗時間:"+timeList(new ArrayList(values)));   
     System.out.println("LinkedList消耗時間:"+timeList(new LinkedList(values)));   
 }   

}

我得到的輸出 是:ArrayList消耗時間:15
LinkedList消耗時間:2596
這個結(jié)果不是固定的募壕,但是基本上ArrayList的 時間要明顯小于LinkedList的時間。因此在這種情況下不宜用LinkedList语盈。二分查找法使用的隨機訪問(random access)策略舱馅,而LinkedList是不支持快速的隨機訪問的。對一個LinkedList做隨機訪問所消耗的時間與這個list的大小是成比例 的刀荒。而相應(yīng)的代嗤,在ArrayList中進行隨機訪問所消耗的時間是固定的。
這是否表明ArrayList總是比LinkedList性能要好呢缠借?這并不一定干毅,在某些情況 下LinkedList的表現(xiàn)要優(yōu)于ArrayList,有些算法在LinkedList中實現(xiàn)時效率更高泼返。比方說硝逢,利用 Collections.reverse方法對列表進行反轉(zhuǎn)時,其性能就要好些绅喉。
看這樣一個例子渠鸽,加入我們有一個列表,要對其進行大量的插入和刪除操作柴罐,在這種情況下 LinkedList就是一個較好的選擇徽缚。請看如下一個極端的例子,我們重復(fù)的在一個列表的開端插入一個元素:

Java代碼
package com.mangocity.test;

import java.util.*;
public class ListDemo {
static final int N=50000;
static long timeList(List 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耗時:"+timeList(new ArrayList()));
System.out.println("LinkedList耗時:"+timeList(new LinkedList()));
}
}
這時我的輸出結(jié)果是:ArrayList耗時:2463

                       LinkedList耗時:15 

這和前面一個例子的結(jié)果截然相反革屠,當一個元素被加到ArrayList的最開端時凿试,所有已經(jīng)存在的元素都會后 移,這就意味著數(shù)據(jù)移動和復(fù)制上的開銷屠阻。相反的红省,將一個元素加到LinkedList的最開端只是簡單的未這個元素分配一個記錄,然后調(diào)整兩個連接国觉。在 LinkedList的開端增加一個元素的開銷是固定的吧恃,而在ArrayList的開端增加一個元素的開銷是與ArrayList的大小成比例的。

二.空間復(fù) 雜度
在LinkedList中有一個私有的內(nèi)部類麻诀,定義如下:

Java代碼
private static class Entry {
Object element;
Entry next;
Entry previous;
}

每個Entry對象 reference列表中的一個元素痕寓,同時還有在LinkedList中它的上一個元素和下一個元素傲醉。一個有1000個元素的LinkedList對象將 有1000個鏈接在一起的Entry對象,每個對象都對應(yīng)于列表中的一個元素呻率。這樣的話硬毕,在一個LinkedList結(jié)構(gòu)中將有一個很大的空間開銷,因為 它要存儲這1000個Entity對象的相關(guān)信息礼仗。
ArrayList使用一個內(nèi)置的數(shù)組來存儲元素吐咳,這個數(shù)組的起始容量是10.當數(shù)組需要增長時,新的容量按 如下公式獲得:新容量=(舊容量*3)/2+1元践,也就是說每一次容量大概會增長50%韭脊。這就意味著,如果你有一個包含大量元素的ArrayList對象单旁, 那么最終將有很大的空間會被浪費掉沪羔,這個浪費是由ArrayList的工作方式本身造成的。如果沒有足夠的空間來存放新的元素象浑,數(shù)組將不得不被重新進行分 配以便能夠增加新的元素蔫饰。對數(shù)組進行重新分配,將會導(dǎo)致性能急劇下降愉豺。如果我們知道一個ArrayList將會有多少個元素篓吁,我們可以通過構(gòu)造方法來指定 容量。我們還可以通過trimToSize方法在ArrayList分配完畢之后去掉浪費掉的空間粒氧。

三.總結(jié)
ArrayList和LinkedList在性能上各 有優(yōu)缺點越除,都有各自所適用的地方,總的說來可以描述如下:
1.對ArrayList和LinkedList而言外盯,在列表末尾增加一個元素所花的開銷都是固定的摘盆。對 ArrayList而言,主要是在內(nèi)部數(shù)組中增加一項饱苟,指向所添加的元素孩擂,偶爾可能會導(dǎo)致對數(shù)組重新進行分配;而對LinkedList而言箱熬,這個開銷是 統(tǒng)一的类垦,分配一個內(nèi)部Entry對象。

2.在ArrayList的 中間插入或刪除一個元素意味著這個列表中剩余的元素都會被移動城须;而在LinkedList的中間插入或刪除一個元素的開銷是固定的蚤认。

3.LinkedList不 支持高效的隨機元素訪問。

4.ArrayList的空 間浪費主要體現(xiàn)在在list列表的結(jié)尾預(yù)留一定的容量空間糕伐,而LinkedList的空間花費則體現(xiàn)在它的每一個元素都需要消耗相當?shù)目臻g

可以這樣說:當操作是在一列 數(shù)據(jù)的后面添加數(shù)據(jù)而不是在前面或中間,并且需要隨機地訪問其中的元素時,使用ArrayList會提供比較好的性能砰琢;當你的操作是在一列數(shù)據(jù)的前面或中 間添加或刪除數(shù)據(jù),并且按照順序訪問其中的元素時,就應(yīng)該使用LinkedList了。

所以,如果只是查找特定位置的元素或只在集合的末端增加陪汽、移除元素训唱,那么使用Vector或ArrayList都可以。如果是對其它指定位置的插入挚冤、刪除操作况增,最好選擇LinkedList

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市训挡,隨后出現(xiàn)的幾起案子澳骤,更是在濱河造成了極大的恐慌,老刑警劉巖舍哄,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宴凉,死亡現(xiàn)場離奇詭異,居然都是意外死亡表悬,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門丧靡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蟆沫,“玉大人,你說我怎么就攤上這事温治》古樱” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵熬荆,是天一觀的道長舟山。 經(jīng)常有香客問我,道長卤恳,這世上最難降的妖魔是什么累盗? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮突琳,結(jié)果婚禮上若债,老公的妹妹穿的比我還像新娘。我一直安慰自己拆融,他們只是感情好蠢琳,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著镜豹,像睡著了一般傲须。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上趟脂,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天泰讽,我揣著相機與錄音,去河邊找鬼。 笑死菇绵,一個胖子當著我的面吹牛肄渗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咬最,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼翎嫡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了永乌?” 一聲冷哼從身側(cè)響起惑申,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翅雏,沒想到半個月后圈驼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡望几,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年绩脆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片橄抹。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡靴迫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出楼誓,到底是詐尸還是另有隱情玉锌,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布疟羹,位于F島的核電站主守,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏榄融。R本人自食惡果不足惜参淫,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剃袍。 院中可真熱鬧黄刚,春花似錦、人聲如沸民效。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畏邢。三九已至业扒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舒萎,已是汗流浹背程储。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人章鲤。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓摊灭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親败徊。 傳聞我的和親對象是個殘疾皇子帚呼,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容