1. List Overview
List, as its name indicates, is an ordered sequence of elements. When we talk about List, it is a good idea to compare it with Set which is a set of unique and unordered elements. The following is the class hierarchy diagram of Collection. From the hierarchy diagram you can get a general idea of Java Collections.
2. ArrayList vs. LinkedList vs. Vector
From the hierarchy diagram, they all implement
ArrayList is a better choice if your program is thread-safe. Vector and ArrayList require more space as more elements are added. Vector each time doubles its array size, while ArrayList grow 50% of its size each time. LinkedList, however, also implements
Note: The default initial capacity of an ArrayList is pretty small. It is a good habit to construct the ArrayList with a higher initial capacity. This can avoid the resizing cost.
3. ArrayList example
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()); } |
4. LinkedList example
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()); } |
As shown in the examples above, they are similar to use. The real difference is their underlying implementation and their operation complexity.
5. Vector
Vector is almost identical to ArrayList, and the difference is that Vector is synchronized. Because of this, it has an overhead than ArrayList. Normally, most Java programmers use ArrayList instead of Vector because they can synchronize explicitly by themselves.
6. Performance of ArrayList vs. LinkedList
The time complexity comparison is as follows:
* add() in the table refers to add(E e), and remove() refers to remove(int index)
- ArrayList has O(n) time complexity for arbitrary indices of add/remove, but O(1) for the operation at the end of the list.
- LinkedList has O(n) time complexity for arbitrary indices of add/remove, but O(1) for operations at end/beginning of the List.
Â
I use the following code to test their performance:
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); |
And the output is:
ArrayList add: 13265642 LinkedList add: 9550057 ArrayList get: 1543352 LinkedList get: 85085551 ArrayList remove: 199961301 LinkedList remove: 85768810
The difference of their performance is obvious. LinkedList is faster in add and remove, but slower in get. Based on the complexity table and testing results, we can figure out when to use ArrayList or LinkedList. In brief, LinkedList should be preferred if:
- there are no large number of random access of element
- there are a large number of add/remove operations
I believe the add of an ArrayList has amortized complexity of O(1) because it has to double the array every time the buffer is full and we do an add; however, the LinkedList is just O(1) assuming the linkedlist keeps track of the tail of the list.
Great Article
I just run the given program and found unexpected result in case of add element in arraylist and linkedlist. Add in linkedlist taking much time then array list. I was amazed looking the results. So I run only add section removing other (get, remove), getting expected result. (i.e. – linkedlist is faster in adding the element then arraylist).
ArrayList add: 7879257
LinkedList add: 8587097
ArrayList get: 93867
LinkedList get: 91681319
ArrayList remove: 471618335
LinkedList remove: 90256678
ArrayList add: 7274670
LinkedList add: 8485124
ArrayList get: 92160
LinkedList get: 96073854
ArrayList remove: 125224587
LinkedList remove: 85604729
ArrayList add: 8384430
LinkedList add: 6260483
ArrayList get: 151893
LinkedList get: 92966440
ArrayList remove: 135471844
LinkedList remove: 87632677
ArrayList add: 6741336
LinkedList add: 10437551
ArrayList get: 161706
LinkedList get: 90528038
ArrayList remove: 458203076
LinkedList remove: 92194172
ArrayList add: 6850563
LinkedList add: 8046084
ArrayList get: 168533
LinkedList get: 90907772
ArrayList remove: 467550493
LinkedList remove: 94564734
=================================
ArrayList add: 7445337
LinkedList add: 5977603
ArrayList add: 5499309
LinkedList add: 4195415
ArrayList add: 7945816
LinkedList add: 4072108
ArrayList add: 7350616
LinkedList add: 4373762
ArrayList add: 10162351
LinkedList add: 6481923
yes but you haven’t tested add(int index, E element). This is much faster in LinkedList O(1).
Thanks very much this is a sufficiently article good job (y)
String foo = "bar";
fixed.
“ArrayList” is a better choice if your program is thread-safe – i believe here it should be Vector
i love this site
“The difference of their performance is obvious. LinkedList is faster in add and remove, but slower in get. Based on the complexity table and testing results, we can figure out when to use ArrayList or LinkedList. In brief, LinkedList should be preferred if:..”
It isn’t obvious. You didn’t mentioned which Java version did you use for the benchmark. It was true in Java 1.5 and under.
You made a fatal mistake here. Put your whole benchmark code in a procedure and call it 2-4 times. You will get completely different numbers:
First call with max value 13 (it’s higher than the default capacity of the ArrayList):
ArrayList add: 324103 (OMG)
LinkedList add: 8608
ArrayList get: 3311 (2x faster)
LinkedList get: 6621
ArrayList get iterate: 101634 (slightly faster)
LinkedList get iterate: 128119
ArrayList remove: 4966 (moderately faster)
LinkedList remove: 7283
———————————————
4th call with max 13:
ArrayList add: 3973 (OMG2 it’s like a magic)
LinkedList add: 5297
ArrayList get: 993 (2x faster)
LinkedList get: 2318
ArrayList get iterate: 3642 (almost the same)
LinkedList get iterate: 3641
ArrayList remove: 1656 (2x faster)
LinkedList remove: 3311
——————————————
4th call with max 10000
ArrayList add: 131098 (moderately faster)
LinkedList add: 189032
ArrayList get: 305233 (15x faster)
LinkedList get: 43127889
ArrayList get iterate: 37409 (almost 2x faster)
LinkedList get iterate: 68859
ArrayList remove: 45355 (almost 2x faster)
LinkedList remove: 85743
The magic what happens is called bytecode optimalization. Java is fast today.
—————————————————————————————————————————–
Conclusion:
1) Always use ArrayList except you need to insert always at the front
2) Benchmark your application if it is slow
3) Don’t use premature optimalization because you don’t know what happens under the hood in the JVM
not bad…gonna look into this later!
BOOKMARKED!!!!
It is worth noting that in this example as its known the list size is 10,0000 then the ArrayList is actually faster for insertions if initialized with the desired size, thereby creating just one array to back the list. Like so:
ArrayList arrayList = new ArrayList(10000);
This article is very benefit. Thank you.
Thanks a lot!
Just boning up on Java, coming back to it after a long hiatus when working in C/C++. Adding to an array one element at a time is of course going to be slow, as the system must find storage for the size of the existing array +1. This isn’t a very smart approach to using extensible arrays, or anything for that matter.
Why not allocate arrays arbitrarily large with a constant or statistically managed chunk size so many elements can be appended onto the array before any additional memory needs to be allocated? If you’re on a machine with enough resources to run Java (instead of C/C++) the you can spare the temporarily unused memory, so why not use this approach?
TVMIA
what is mean that ” Vector is similar with ArrayList, but it is synchronized. “
Under point 6 in table there is a mistake for add() method – it should be reversed, as it is amortized for ArrayList (it does reallocation not each method call) and it is constant for LinkedList
Is LinkedList threadsafe?
under 6. in the time complexity table array get() vs list get() is the wrong way around.
Thanks a lott!!!good Article!
Thanks a lot for this article, it was very helpfull.
There is a little mistake in ‘4. LinkedList example’ at line with iter2 implementation. Convert ‘al’ to ‘ll’;)
As mentioned, unfortunately both ArrayList and LinkedList have their drawbacks: ArrayList is slow if
insertion/removal does not happen at the end and LinkedList is slow at
accessing elements by index.
There is a new list implementation called GapList which combines the strengths of both ArrayList
and LinkedList. It has been designed as drop-in replacement for both ArrayList and LinkedList and therefore implements both the interfaces List and Deque.
GapList’s implementation guarantees efficient random access to elements by index (as ArrayList does) and at the same time efficient adding and removing elements to and from head and tail of the list (as LinkedList does).
You find more information about GapList at http://java.dzone.com/articles/gaplist-%E2%80%93-lightning-fast-list.