I've always been one to simply use:
List<String> names = new ArrayList<>();
I use the interface as the type name for portability, so that when I ask questions such as these I can rework my code.
When should LinkedList
be used over ArrayList
and vice-versa?
I know this is an old post, but I honestly can't believe nobody mentioned that
LinkedList
implementsDeque
. Just look at the methods inDeque
(andQueue
); if you want a fair comparison, try runningLinkedList
againstArrayDeque
and do a feature-for-feature comparison.TL;DR due to modern computer architecture,
ArrayList
will be significantly more efficient for nearly any possible use-case - and thereforeLinkedList
should be avoided except some very unique and extreme cases.In theory, LinkedList has an O(1) for the
add(E element)
Also adding an element in the mid of a list should be very efficient.
Practice is very different, as LinkedList is a Cache Hostile Data structure. From performance POV - there are very little cases where
LinkedList
could be better performing than the Cache-friendlyArrayList
.Here are results of a benchmark testing inserting elements in random locations. As you can see - the array list if much more efficient, although in theory each insert in the middle of the list will require "move" the n later elements of the array (lower values are better):
Working on a later generation hardware (bigger, more efficient caches) - the results are even more conclusive:
LinkedList takes much more time to accomplish the same job. source Source Code
There are two main reasons for this:
Mainly - that the nodes of the
LinkedList
are scattered randomly across the memory. RAM ("Random Access Memory") isn't really random and blocks of memory need to be fetched to cache. This operation takes time, and when such fetches happen frequently - the memory pages in the cache need to be replaced all the time -> Cache misses -> Cache is not efficient.ArrayList
elements are stored on continuous memory - which is exactly what the modern CPU architecture is optimizing for.Secondary
LinkedList
required to hold back/forward pointers, which means 3 times the memory consumption per value stored compared toArrayList
.DynamicIntArray, btw, is a custom ArrayList implementation holding
Int
(primitive type) and not Objects - hence all data is really stored adjacently - hence even more efficient.A key elements to remember is that the cost of fetching memory block, is more significant than the cost accessing a single memory cell. That's why reader 1MB of sequential memory is up to x400 times faster than reading this amount of data from different blocks of memory:
Source: Latency Numbers Every Programmer Should Know
Just to make the point even clearer, please check the benchmark of adding elements to the beginning of the list. This is a use-case where, in-theory, the
LinkedList
should really shine, andArrayList
should present poor or even worse-case results:Note: this is a benchmark of the C++ Std lib, but my previous experience shown the C++ and Java results are very similar. Source Code
Copying a sequential bulk of memory is an operation optimized by the modern CPUs - changing theory and actually making, again,
ArrayList
/Vector
much more efficientCredits: All benchmarks posted here are created by Kjell Hedström. Even more data can be found on his blog
ArrayList extends AbstractList and implements the List Interface. ArrayList is dynamic array.
It can be said that it was basically created to overcome the drawbacks of arrays
The LinkedList class extends AbstractSequentialList and implements List,Deque, and Queue interface.
Performance
arraylist.get()
is O(1) whereaslinkedlist.get()
is O(n)arraylist.add()
is O(1) andlinkedlist.add()
is 0(1)arraylist.contains()
is O(n) andlinkedlist.contains()
is O(n)arraylist.next()
is O(1) andlinkedlist.next()
is O(1)arraylist.remove()
is O(n) whereaslinkedlist.remove()
is O(1)In arraylist
iterator.remove()
is O(n)whereas In linkedlist
iterator.remove()
is O(1)ArrayList
is essentially an array.LinkedList
is implemented as a double linked list.The
get
is pretty clear. O(1) forArrayList
, becauseArrayList
allow random access by using index. O(n) forLinkedList
, because it needs to find the index first. Note: there are different versions ofadd
andremove
.LinkedList
is faster in add and remove, but slower in get. In brief,LinkedList
should be preferred if:=== ArrayList ===
=== LinkedList ===
add(E e)
add(int index, E element)
Here is a figure from programcreek.com (
add
andremove
are the first type, i.e., add an element at the end of the list and remove the element at the specified position in the list.):One of the tests I saw on here only conducts the test once. But what I have noticed is that you need to run these tests many times and eventually their times will converge. Basically the JVM needs to warm up. For my particular use case I needed to add/remove items to a last that grows to about 500 items. In my tests
LinkedList
came out faster, with linkedLinkedList
coming in around 50,000 NS andArrayList
coming in at around 90,000 NS... give or take. See the code below.Joshua Bloch, the author of LinkedList:
Link: https://twitter.com/joshbloch/status/583813919019573248
I'm sorry for the answer for being not that informative as the other answers, but I thought it would be the most interesting and self-explanatory.