ps:推薦大家先去了解一下鍊錶這個資料結構。
arraylist和linkedlist可以說是日常業務開發中最常使用的容器類了,同時,他們的區別也是面試高發區,雖然很簡單,但是我們總是不能說的完整,今天就通過對他們原始碼的閱讀來進一步加深理解。
首先,看他們類的定義可以發現:
他們都是實現了list介面,這個介面幹了什麼呢?
這個介面定義了對列表的一些基本操作,如add,contains,indexof,remove
等基本方法,由他的實現類各自進行實現。
因此,當你只是需要乙個列表進行常規的新增移除查詢操作,那麼arraylist和linkedlist在使用體驗(不考慮效能)上基本沒有區別,你甚至不用關心他的內部實現,而是呼叫一些list介面的方法就ok。
那麼他們的具體實現有哪些區別呢?
下面對他們常用的方法進行原始碼的閱讀。
成員變數
arraylist有兩個成員變數,圖中可以看到,乙個object的陣列,乙個int型別的size,用來定義陣列的大小。
get()方法
首先檢查傳入的index,然後返回陣列在該index的值。
add()方法
首先確保容量夠用,然後將新加入的物件放在陣列尾部。
remove()方法
首先確保容量夠用,然後計算出需要移動的數量,例如size=10,要刪除index=5的元素,則需要移動後面的四個元素,然後呼叫system.arraycopy()
方法,將陣列的後面4個依次向前移動一位,然後將陣列最後一位置為null。
成員變數
linkedlist本身的屬性比較少,主要有三個,乙個是size,表明當前有多少個節點;乙個是first代表第乙個節點;乙個是last代表最後乙個節點。
get()方法
首先檢查傳入的index是否合法,然後呼叫了node(index)
方法,那麼來看看node()
方法。
判斷index值是否大於總數的一半。
如果小於,則從first節點向後遍歷,直到找到index節點,然後返回該節點的值。
如果大於,則從last節點向前遍歷,直到找到index節點,然後返回該節點的值。
add()方法
add方法,直接呼叫了linklast方法,將傳入的值作為最後乙個節點鏈結在鍊錶上。
remove()方法
由上面的常用方法可以發現
1.arraylist使用陣列儲存元素,因此在查詢時速度較快,直接返回該位置的元素即可,時間複雜度為o(1);而linkedlist使用雙向鍊錶儲存元素,在查詢時需要從頭或者尾遍歷至查詢元素,時間複雜度為o(n/2);
2.還是因為儲存方式的問題,arraylist在插入或者刪除時,需要移動插入位置之後的所有元素,因此速度較慢,時間複雜度為o(n)。而linkedlist只需要找到該位置,移動」指標」即可,時間複雜度為o(1)。
當你對列表更多的進行查詢,即獲取某個位置的元素時,應當優先使用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時,如果你能預估大小,最好直接定義初始容量,這樣能節省頻繁的擴容帶來的額外開支。
初始化定義容量的構造方法為:
Array List和ArrayList的區別與
定義 public abstract class array icloneable,ilist,icollection,ienumerable,istructuralcomparable,istructuraequatable 陣列在記憶體中是連續儲存的,所以它的索引速度是非常的快,而且賦值與修改元...
LinkedList和ArrayList的區別
對於集合collection下的list介面,有兩個實現類,arraylist和linkedlist,那麼他們兩個有什麼區別呢。arraylist的底層由陣列實現,而linkedlist的底層由雙向鍊錶實現,底層的不同才是他們區別的根源。然而因為他們繼承於同乙個父介面,他們的很多方法都是相同的。關於...
ArrayList和LinkedList的面試題
一 arraylist為什麼是執行緒不安全的?arraylist在新增乙個元素的時候,它可能會有兩步來完成 1.在 items size 的位置存放此元素 2.增大 size 的值。在單執行緒執行的情況下,如果 size 0,新增乙個元素後,此元素在位置 0,而且 size 1 而如果是在多執行緒情...