翻译自: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:
没有大量的随机访问元素的操做;
有大量增长/删除元素的操做。线程