Arraylist和linkedlist的區別(JDK源碼閱讀)

PS:推薦你們先去了解一下鏈表這個數據結構。node

ArrayList和LinkedList能夠說是平常業務開發中最常使用的容器類了,同時,他們的區別也是面試高發區,雖然很簡單,可是咱們老是不能說的完整,今天就經過對他們源碼的閱讀來進一步加深理解。面試

首先,看他們類的定義能夠發現: 數組

他們都是實現了List接口,這個接口乾了什麼呢?bash

這個接口定義了對列表的一些基本操做,如add,contains,indexof,remove等基本方法,由他的實現類各自進行實現。數據結構

所以,當你只是須要一個列表進行常規的添加移除查找操做,那麼ArrayList和LinkedList在使用體驗(不考慮性能)上基本沒有區別,你甚至不用關心他的內部實現,而是調用一些List接口的方法就ok。性能

那麼他們的具體實現有哪些區別呢?學習

下面對他們經常使用的方法進行源碼的閱讀。編碼

ArrayList

成員變量

ArrayList有兩個成員變量,圖中能夠看到,一個Object的數組,一個int類型的size,用來定義數組的大小。spa

get()方法

首先檢查傳入的index,而後返回數組在該index的值。3d

add()方法

首先確保容量夠用,而後將新加入的對象放在數組尾部。

remove()方法

首先確保容量夠用,而後計算出須要移動的數量,例如size=10,要刪除index=5的元素,則須要移動後面的四個元素,而後調用System.arraycopy()方法,將數組的後面4個依次向前移動一位,而後將數組最後一位置爲null。

LinkedList

成員變量

LinkedList自己的屬性比較少,主要有三個,一個是size,代表當前有多少個節點;一個是first表明第一個節點;一個是last表明最後一個節點。

get()方法

首先檢查傳入的index是否合法,而後調用了node(index)方法,那麼來看看node()方法。

判斷index值是否大於總數的一半。

若是小於,則從first節點向後遍歷,直到找到index節點,而後返回該節點的值。

若是大於,則從last節點向前遍歷,直到找到index節點,而後返回該節點的值。

add()方法

add方法,直接調用了linklast方法,將傳入的值做爲最後一個節點連接在鏈表上。

remove()方法

remove方法的思路是什麼呢?從頭開始遍歷鏈表,當找到要刪除的節點,將他刪除。刪除的方法呢?將該節點的先後節點連接起來,相似於下圖:

對比

由上面的經常使用方法能夠發現

1.ArrayList使用數組存儲元素,所以在查詢時速度較快,直接返回該位置的元素便可,時間複雜度爲O(1);而LinkedList使用雙向鏈表存儲元素,在查詢時須要從頭或者尾遍歷至查詢元素,時間複雜度爲O(n/2);

2.仍是由於存儲方式的問題,ArrayList在插入或者刪除時,須要移動插入位置以後的全部元素,所以速度較慢,時間複雜度爲O(n)。而LinkedList只須要找到該位置,移動」指針」便可,時間複雜度爲O(1)。

結論

其實在平常的開發中,ArrayList更受歡迎,並且能夠完成不少的任務,可是仍有一些特殊的情景適合使用LinkedList。他們的使用場景以下:

當你對列表更多的進行查詢,即獲取某個位置的元素時,應當優先使用ArrayList;當你對列表須要進行頻繁的刪除和增長,而不多使用查詢時,優先使用LinkedList;

注意事項!

1.上述結論適用於廣泛的情景,有些極端狀況不必定符合。好比頻繁的在數組結尾附近插入數據,ArrayList也快於LinkedList。

2.LinkedList使用的空間大於ArrayList,由於本質上,ArrayList在每一個位置存儲了元素,而LinkedList存儲了元素+前面節點+後面節點。

擴展

咱們知道ArrayList和LinkedList都是有size的,那麼當添加的元素過多,他們怎麼擴容呢?

ArrayList:

ArrayList使用數組存儲元素,所以擴容時爲:

能夠看到,每次擴容後的大小爲以前的1.5倍。

int newCapacity = oldCapacity + (oldCapacity >> 1);
複製代碼

,並且以後有一個複製所有元素的操做,這個操做很費時間。

LinkedList:

因爲LinkedList是一個雙向鏈表,所以不須要擴容機制,直接在先後添加元素便可。

所以:在使用ArrayList時,若是你能預估大小,最好直接定義初始容量,這樣能節省頻繁的擴容帶來的額外開支。

初始化定義容量的構造方法爲:

後記

其實想寫這個好久了,一直拖延着,今天終於回憶起了面試的時候被ArrayList和LinkedList支配的恐懼。(都喜歡問,一直問(校招))。所以趁熱打鐵,閱讀了他們的源碼並記錄下來。相信經常回顧之下不會再受困於此,也能讓平常工做的編碼水平有些許提高。

完。





ChangeLog

2018-10-11 完成

以上皆爲我的所思所得,若有錯誤歡迎評論區指正。

歡迎轉載,煩請署名並保留原文連接。

聯繫郵箱:huyanshi2580@gmail.com

更多學習筆記見我的博客------>呼延十

相關文章
相關標籤/搜索