翻譯自:ArrayList vs. LinkedList vs. Vectorjava
就像它的名字同樣,List是一個元素的有序序列。當咱們討論列表時把它與Set(兩兩不等且無序的元素集合)進行比較是一個好主意。下面是容器的類層次圖。從這個層次圖中能夠了解Java容器的通常概念。
程序員
從上圖可知,它們都實現了List接口,並且用法很類似。它們主要的不一樣在於它們的實現致使的對不一樣的操做有不一樣的性能。
ArrayList被實現爲一個大小可變的數組。當有更多的元素添加到ArrayList時,它的大小會動態的增長。由於ArrayList本質上是一個數組,因此能夠經過get()和set()方法直接訪問它的元素。
LinkedList被實現爲一個雙向鏈表,在增長和刪除元素的時候比ArrayList的性能要好,而對於get()和set()方法性能就不及ArrayList了。
Vector與ArrayList類似,但它是線程同步的。
當程序是線程安全的時候,ArrayList是一個更好的選擇。當添加更多的元素時,ArrayList和Vector會請求更多的空間,Vector每次會申請兩倍於當前大小的空間,而ArrayList每次只會增長當前大小50%的空間。LinkedList還實現了Queue接口,使得它比ArrayList和Vector有更多的方法,好比offer()、peek()、poll()等。
注意:ArrayList的初始容量很是小,因此以較大的初始容量構造ArrayList是一個很好的習慣,這樣能夠避免從新分配空間的花費。數組
ArrayList<Integer> al = new ArrayList<Integer>(); al.add(3); al.add(2); al.add(1); al.add(4); al.add(5); al.add(6); al.add(6); Iterator<Integer> iter1 = al.iterator(); while(iter1.hasNext()){ System.out.println(iter1.next()); }
LinkedList<Integer> ll = new LinkedList<Integer>(); ll.add(3); ll.add(2); ll.add(1); ll.add(4); ll.add(5); ll.add(6); ll.add(6); Iterator<Integer> iter2 = ll.iterator(); while(iter2.hasNext()){ System.out.println(iter2.next()); }
就像上面示例中展現的同樣,它們的用法很類似。真正的不一樣在於背後的實現和他們操做的複雜度。安全
Vector和ArrayList幾乎徹底同樣,不一樣點是Vector是線程同步的。正由於這樣,Vector比ArrayList有一個額外的開銷。一般狀況下,大多數Java程序員都會使用ArrayList,由於他們能夠靠本身明確的實現同步。markdown
時間複雜度比較以下:
*表中add()指add(E e),remove()指remove(int index)
*ArrayList在任意位置增長/刪除操做的時間複雜度爲O(n),但在列表尾的時間複雜度爲O(1)。
*LinkedList在任意位置增長/刪除操做的時間複雜度爲O(n),但在列表頭/尾的時間複雜度爲O(1)。
能夠用下面的代碼測試它們的性能:性能
ArrayList<Integer> arrayList = new ArrayList<Integer>(); LinkedList<Integer> linkedList = new LinkedList<Integer>(); // ArrayList add long startTime = System.nanoTime(); for (int i = 0; i < 100000; i++) { arrayList.add(i); } long endTime = System.nanoTime(); long duration = endTime - startTime; System.out.println("ArrayList add: " + duration); // LinkedList add startTime = System.nanoTime(); for (int i = 0; i < 100000; i++) { linkedList.add(i); } endTime = System.nanoTime(); duration = endTime - startTime; System.out.println("LinkedList add: " + duration); // ArrayList get startTime = System.nanoTime(); for (int i = 0; i < 10000; i++) { arrayList.get(i); } endTime = System.nanoTime(); duration = endTime - startTime; System.out.println("ArrayList get: " + duration); // LinkedList get startTime = System.nanoTime(); for (int i = 0; i < 10000; i++) { linkedList.get(i); } endTime = System.nanoTime(); duration = endTime - startTime; System.out.println("LinkedList get: " + duration); // ArrayList remove startTime = System.nanoTime(); for (int i = 9999; i >=0; i--) { arrayList.remove(i); } endTime = System.nanoTime(); duration = endTime - startTime; System.out.println("ArrayList remove: " + duration); // LinkedList remove startTime = System.nanoTime(); for (int i = 9999; i >=0; i--) { linkedList.remove(i); } endTime = System.nanoTime(); duration = endTime - startTime; System.out.println("LinkedList remove: " + duration);
輸出以下:測試
ArrayList add: 13265642 LinkedList add: 9550057 ArrayList get: 1543352 LinkedList get: 85085551 ArrayList remove: 199961301 LinkedList remove: 85768810
性能差異很明顯,LinkedList在增長/刪除元素方面更快,在訪問元素時更慢。根據時間複雜度表和測試結果,咱們能夠知道何時用ArrayList或LinkedList。簡單地說,在下面的狀況時應該用LinkedList:
沒有大量的隨機訪問元素的操做;
有大量增長/刪除元素的操做。線程