Java中ArrayList和LinkedList區別

ArrayList和Vector內部是使用可増長數組實現的,可以認爲ArrayList或者Vector封裝了對內部數組的操作,比如向數組中添加、刪除、插入新的元素或者數據的擴展和重定向。所以使用get和set方法是花費常數時間的,但是如果插入或者刪除元素,除非插入或者刪除的位置都在表末尾,否則代碼開銷會很大,因爲裏面需要數組的移動。
LinkedList使用了循環雙向鏈表數據結構,所以get會非常消耗資源,除非位置離頭部很近。但是插入或者刪除元素花費常數時間。與基於數組ArrayList相比,這是兩種截然不同的實現技術,這也決定了它們將適用於完全不同的工作場景。
ArrayList和LinkedList的大致區別如下:
1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。
2.對於隨機訪問get和set,ArrayList絕對優於LinkedList,因爲LinkedList要移動指針。
3.對於新增和刪除操作add和remove,LinkedList比較佔優勢,因爲ArrayList要移動數據。

數組和鏈表是數據結構中的概念,數組有什麼特點,鏈表有什麼特點,它們在內存裏大致是怎麼分佈的?

數組:
定義一個數組,只需指定一個長度即可。然後就可以通過變量名+索引(或者說下標)的形式訪問數組元素了,下標不能超過數組長度,否則就會發生索引越界異常。比如數組a,長度是10,那麼第一個元素就是a[0],最後一個就是a[9]。想訪問哪個元素只要指定下標就可以了。像這種可以隨意訪問任何元素的,有個專用名詞叫做隨機訪問。

它在內存中是如何分佈,才支持隨機訪問的?
其實數組在內存中是一段連續的空間,可以將它想象成一個×××,一個格子緊挨着一個格子。數組名,也就是這個a,指向了這個空間的起始處地址,也就是數組的第一個元素的地址,所以其實和a[0]指向的是同一個地方。但a和a[0]的含義不一樣,a表示內存地址,a[0]表示這個地址上存的元素。這裏的下標0其實指的是相對於起始處地址的偏移量。0表示沒有偏移,所以就是起始處地址的那個元素,也即第一個元素。

a[1]表示相對於起始處地址偏移量爲1的那個元素,實際可以認爲底層執行的是(a + 1)。a+1表示從起始地址開始向後偏移1個之後的地址,那麼(星號)的意思就是取出那個地址上存儲的元素。因爲向後偏移了1個,其實就是第二個,所以a[1]叫取出數組的第二個元素。

因數組在內存中是一段連續的空間,所以不管訪問哪個元素都是這兩步,加上偏移量,然後取數據。這就是它支持隨機訪問的原因。說白了就是所有元素按順序挨在了一起。也可以看出來,不管數組的長度是多長,訪問元素的方式都是這兩步,都在常量的時間內完成。所以按索引訪問數組元素的時間複雜度就是O(1)。

ArrayList只不過是對數組的包裝,因爲數組在內存中分配時必須指定長度,且一旦分配好後便無法再增加長度,即不可能在原數組後面再接上一段的。ArrayList之所以可以一直往裏添加,是因爲它內部做了處理。當底層數組填滿後,它會再分配一個更大的新的數組,把原數組裏的元素拷貝過來,然後把原數組拋棄掉。使用新的數組作爲底層數組來繼續存儲。

鏈表:
LinkedList也實現了List接口,也可以按索引訪問元素,表面上用起來感覺差不多,但是其底層卻有天壤之別。

與數組一下子分配好指定長度的空間備用不同,鏈表不會預先分配空間。而是在每次添加一個元素時臨時專門爲它自己分配一個空間。

因爲內存空間的分配是由操作系統完成的,可以說每次分配的位置都是隨機的,並沒有確定的規律。所以說鏈表的每個元素都在完全不同的內存地址上,那我們該如何找到它們呢?

唯一的做法就是把每個元素的內存地址都要保存起來。怎麼保存呢?那就讓上一個元素除了存儲具體的數據之外,也存儲一份下一個元素在內存中的地址。整個就像前後按順序依次相連的一條鏈,我們只要保存第一個元素的內存地址,就可以順藤摸瓜找到所有的元素。

這其實就像一個挖寶藏遊戲,假設共10步,告訴你第一步去哪裏挖。然後挖出一個字條,上面寫着第二步去哪裏挖。依次這樣挖下去。第九步挖出字條後才知道寶藏的位置,然後第十步就把它挖出來了。可見爲了得到寶藏必須這樣一步一步挖下去。中間的任何一步都不能跳過,因爲第十步寶藏的位置在第九步裏放着呢,第九步的位置在第八步裏放着呢,依次倒着下來就到了第一步的位置,而第一步的位置已經告訴你了。

數組是康莊大道、四平八穩,彷彿回家,輕車熟路。鏈表是曲徑通幽、人跡罕至,猶如探險,步步爲營。

可見按索引訪問鏈表元素時,必須從頭一個個遍歷,而且鏈表越長,位置越靠後,所需花費的時間就越長。所以按索引訪問鏈表元素的時間複雜度就是O(n),n爲鏈表的長度。也說明了鏈表不支持隨機訪問。所以ArrayList就實現了RandomAccess(隨機訪問)接口,而LinkedList就沒有。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章