首頁>技術>

1、ArrayList和LinkedList的區別?

是否保證執行緒安全:ArrayList和LinkedList都是不同步的,也就是不保證執行緒安全;

底層資料結構:Arraylist底層使用的是Object陣列;LinkedList底層使用的是雙向迴圈連結串列資料結構;

插入和刪除是否受元素位置的影響:①ArrayList採用陣列儲存,所以插入和刪除元素的時間複雜度受元素位置的影響。比如:執行add(E e)方法的時候,ArrayList會預設在將指定的元素追加到此列表的末尾,這種情況時間複雜度就是O(1)。但是如果要在指定位置i插入和刪除元素的話(add(int index,E element))時間複雜度就為O(n-i)。因為在進行上述操作的時候集合中第i和第i個元素之後的(n-i)個元素都要執行向後位/向前移一位的操作。②LinkedList採用連結串列儲存,所以插入,刪除元素時間複雜度不受元素位置的影響,都是近似O(1)而陣列為近似O(n)。

是否支援快速隨機訪問:LinkedList不支援高效的隨機元素訪問,而ArrayList實現了RandmoAccess介面,所以有隨機訪問功能。快速隨機訪問就是透過元素的序號快速獲取元素物件(對應於get(int index)方法)。

記憶體空間佔用:ArrayList的空間浪費主要體現在在list列表的結尾會預留一定的容量空間,而LinkedList的空間花費則體現在它的每一個元素都需要消耗比ArrayList更多的空間(因為要存放直接後繼和直接前驅以及資料)。

補充:ArrayList的增刪未必就是比LinkedList要慢:

如果增刪都是在末尾來操作【每次呼叫的都是remove()和add()】,此時ArrayList就不需要移動和複製陣列來進行操作了。如果資料量有百萬級的時,速度是會比LinkedList要快的。

如果刪除操作的位置是在中間。由於LinkedList的消耗主要是在遍歷上,ArrayList的消耗主要是在移動和複製上(底層呼叫的是arrayCopy()方法,是native方法)。LinkedList的遍歷速度是要慢於ArrayList的複製移動速度的如果資料量有百萬級的時,還是ArrayList要快。

2、ArrayList實現RandomAccess介面有何作用?為何LinkedList卻沒實現這個介面?

RandomAccess介面只是一個標誌介面,只要List集合實現這個介面,就能支援快速隨機訪問。實現RandomAccess介面的List集合採用一般的for迴圈遍歷,而未實現這介面則採用迭代器,即ArrayList一般採用for迴圈遍歷,而LinkedList一般採用迭代器遍歷;

ArrayList用for迴圈遍歷比iterator迭代器遍歷快,LinkedList用iterator迭代器遍歷比for迴圈遍歷快。所以說,當我們在做專案時,應該考慮到List集合的不同子類採用不同的遍歷方式,能夠提高效能。

Java集合類中元素的訪問分為隨機訪問和順序訪問。隨機訪問一般是透過index下標訪問,行為類似陣列的訪問。而順序訪問類似於連結串列的訪問,通常為迭代器遍歷。

以List介面及其例項為例。ArrayList是典型的隨機訪問型,而LinkedList則是順序訪問型。List介面既定義了下標訪問方法又定義了迭代器方法。所以其例項既可使用下標隨機訪問也可以使用迭代器進行遍歷。但這兩種方式的效能差異很明顯。

RandomAccess介面

JDK中的RandomAccess介面是一個標記介面,它並未定義方法。其目的是用於指示實現類具有隨機訪問特性,在遍歷時使用下標訪問較迭代器更快。

3.ArrayList的擴容機制?

當使用add方法的時候首先呼叫ensureCapacityInternal方法,傳入size+1進去,檢查是否需要擴充elementData陣列的大小;

newCapacity=擴充陣列為原來的1.5倍(不能自定義),如果還不夠,就使用它指定要擴充的大小minCapacity,然後判斷minCapacity是否大於MAX_ARRAY_SIZE(Integer.MAX_VALUE-8),如果大於,就取Integer.MAX_VALUE;

擴容的主要方法:grow;

ArrayList中copy陣列的核心就是System.arraycopy方法,將original陣列的所有資料複製到copy陣列中,這是一個本地方法。

5.Array和ArrayList有何區別?什麼時候更適合用Array?

Array可以容納基本型別和物件,而ArrayList只能容納物件;

Array是指定大小的,而ArrayList大小是固定的。

什麼時候更適合使用Array:

4.如果列表的大小已經指定,大部分情況下是儲存和遍歷它們;

對於遍歷基本資料型別,儘管Collections使用自動裝箱來減輕編碼任務,在指定大小的基本型別的列表上工作也會變得很慢;

如果你要使用多維陣列,使用[][]比List>更容易。

5.什麼是Iterator?

一些集合類提供了內容遍歷的功能,透過java.util.Iterator介面。這些介面允許遍歷物件的集合。依次操作每個元素物件。當使用Iterators時,在獲得Iterator的時候包含一個集合快照。通常在遍歷一個Iterator的時候不建議修改集合本省。

6.Iterator與ListIterator有什麼區別?

Iterator:只能正向遍歷集合,適用於獲取移除元素。ListIerator:繼承Iterator,可以雙向列表的遍歷,同樣支援元素的修改。

Iterator可以遍歷Set和List集合,而ListIterator只能遍歷List

ListIterator從Iterator介面繼承,然後添加了一些額外的功能,比如新增一個元素、替換一個元素、獲取前面或後面元素的索引位置。

7.什麼叫做快速失敗特性?

從高級別層次來說快速失敗是一個系統或軟體對於其故障做出的響應。一個快速失敗系統設計用來即時報告可能會導致失敗的任何故障情況,它通常用來停止正常的操作而不是嘗試繼續做可能有缺陷的工作。當有問題發生時,快速失敗系統即時可見地發錯錯誤告警。在Java中,快速失敗與iterators有關。如果一個iterator在集合物件上建立了,其它執行緒欲“結構化”的修改該集合物件,併發修改異常(ConcurrentModificationException)丟擲。

8.為什麼Vector類認為是廢棄的或者是非官方不推薦使用?或者說為什麼我們應該一直使用ArrayList而不是Vector?

預設情況下你是非同步訪問的,Vector同步了每個方法,你幾乎從不要那樣做,通常有想要同步的是整個操作序列。同步單個的操作也不安全(如果你迭代一個Vector,你還是要加鎖,以避免其它執行緒在同一時刻改變集合).而且效率更慢。當然同樣有鎖的開銷即使你不需要,這是個很糟糕的方法在預設情況下同步訪問。你可以一直使用Collections.sychronizedList來裝飾一個集合。

事實上Vector結合了“可變陣列”的集合和同步每個操作的實現。這是另外一個設計上的缺陷。Vector還有些遺留的方法在列舉和元素獲取的方法,這些方法不同於List介面,如果這些方法在程式碼中程式設計師更趨向於想用它。儘管列舉速度更快,但是他們不能檢查如果集合在迭代的時候修改了,這樣將導致問題。儘管以上諸多原因,Oracle也從沒宣稱過要廢棄Vector。

9.哪些集合類提供對元素的隨機訪問?

ArrayList、HashMap、TreeMap和HashTable類提供對元素的隨機訪問。

10.哪些集合類是執行緒安全的?

Vector、HashTable、Properties和Stack是同步類,所以它們是執行緒安全的,可以在多執行緒環境下使用。

15
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 快速搞懂.NET 5/.NET Core應用程式的釋出部署