views:

14995

answers:

13

I've always been one to simply use List<String> names = new ArrayList<String>();
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?

+5  A: 

It's an efficiency question. LinkedList is fast for adding and deleting elements, but slow to access a specific element. ArrayList is fast for accessing a specific element but can be slow to add to either end, and especially slow to delete in the middle.

http://www.javafaq.nu/java-article1111.html -- goes more in depth, as does http://en.wikipedia.org/wiki/Linked_list

dgtized
+1  A: 

ArrayList is randomly accessible, while LinkedList is really cheap to expand and remove elements from. For most cases, ArrayList is fine.

Unless you're created large lists and have measured a bottleneck, you'll probably never need to worry about the difference.

Dustin
I like the last part here!
Matthew Schinckel
LinkedList is not cheap to add elements to. It is almost always quicker to add a million elements to an ArrayList than to add them to a LinkedList. And most lists in real-world code are not even a million elements long.
Porculus
At any given point, you know the cost of adding an item to your LinkedList. The ArrayList you do not (in general). Adding a single item to an ArrayList containing a million items *could* take a very long time -- it's an O(n) operation plus double the storage unless you preallocated space. Adding an item to a LinkedList is O(1). My last statement stands.
Dustin
A: 

It depends upon what operations you will be doing more on the List.

ArrayList is faster to access an indexed value. It is much worse when inserting or deleting objects.

To find out more, read any article that talks about the difference betwen arrays and linked lists.

Matthew Schinckel
+12  A: 

When should i use LinkedList?

  • When you need efficient removal in between elements or at the start.
  • When you don't need random access to elements, but can live with iterating over them one by one

When should i use ArrayList?

  • When you need random access to elements ("get the nth. element")
  • When you don't need to remove elements from between others. It's possible but it's slower since the internal backing-up array needs to be reallocated.
  • Adding elements is amortized constant time (meaning every once in a while, you pay some performance, but overall adding is instantly done)
Johannes Schaub - litb
Adding elements is okay, unless you are going to push over the currently allocated number of elements, in which case it becomes fairly expensive (copy all of the items to a new, larger array).
Matthew Schinckel
+1  A: 

In addition to the other good arguments above, you should notice ArrayList implements RandomAccess interface, while LinkedList implements Queue.
So somehow they address slightly different problems, with difference of efficiency and behavior (see their list of methods).

PhiLho
+52  A: 

LinkedList and ArrayList are two different implementations of the List interface. LinkedList implements it with a doubly-linked list. ArrayList implements it with a dynamically resizing array.

As with standard linked list and array operations, the various methods will have different algorithmic runtimes.

For LinkedList

  • get is O(n)
  • add is O(1)
  • remove is O(n)
  • Iterator.remove is O(1)

For ArrayList

  • get is O(1)
  • add is O(1) amortized, but O(n) worst-case since the array must be resized and copied
  • remove is O(n)

LinkedList allows for constant-time insertions or removals, but only sequential access of elements. In other words, you can walk the list forwards or backwards, but grabbing an element in the middle takes time proportional to the size of the list.

ArrayLists, on the other hand, allow random access, so you can grab any element in constant time. But adding or removing from anywhere but the end requires shifting all the latter elements over, either to make an opening or fill the gap. Also, if you add more elements than the capacity of the underlying array, a new array (twice the size) is allocated, and the old array is copied to the new one, so adding to an ArrayList is O(n) in the worst case but constant on average.

So depending on the operations you intend to do, you should choose the implementations accordingly. Iterating over either kind of List is practically equally cheap. (Iterating over an ArrayList is technically faster, but unless you're doing something really performance-sensitive, you shouldn't worry about this -- they're both constants.)

Also, if you have large lists, keep in mind that memory usage is also different. Each element of a LinkedList has more overhead since pointers to the next and previous elements are also stored. ArrayLists don't have this overhead. However, ArrayLists take up as much memory as is allocated for the capacity, regardless of whether elements have actually been added.

The default initial capacity of an ArrayList is pretty small (10 from Java 1.4 - 6). But since the underlying implementation is an array, the array must be resized if you add a lot of elements. To avoid the high cost of resizing when you know you're going to add a lot of elements, construct the ArrayList with a higher initial capacity.

It's worth noting that Vector also implements the List interface and is almost identical to ArrayList. The difference is that Vector is synchronized, so it is thread-safe. Because of this, it also slightly slower than ArrayList. So as far as I understand, most Java programmers avoid Vector in favor of ArrayList since they will probably synchronize explicitly anyway if they care about that.

Jonathan Tran
Forgot to mention insertion costs. In a LinkedList, once you have the correct position, insertion costs O(1), while in an ArrayList it goes up to O(n) - all elements past the insertion point must be moved.
David Rodríguez - dribeas
Regarding the use of Vector: There really is no need to fall back to Vector. The way to do this is with your preferred List implementation and a call to synchronizedList to give it a synchronized wrapper. See: http://java.sun.com/docs/books/tutorial/collections/implementations/wrapper.html
Ryan Cox
Also note that as of Java 6 there's no need to worry about losing performance with a thread-safe class. The JVM is smart enough to optimize those locks away from you if you don't need them.
Alex Beardsley
Linked list add is not always O(1) [or this should say `addLast()` is O(1)]. This is only true if done from within a ListIterator. The add methods in Java's LinkList implementation must search through the list if additions are not on the head or tail. So worst case this is O(n/2) (which really is O(n); but I wrote it this way as it searches forward or backward depending on the given index so is only over at most half the list).
Kevin Brock
A: 

ArrayList is what you want. LinkedList is almost alway a (performance) bug.

Why LinkedList sucks:

  • It uses lots of small memory objects, and therefore impacts performance across the process.
  • Lots of small object are bad for cache-locality.
  • Any indexed operation is requires a traversal, i.e. has O(n) performance. This is not obvious in the source code, leading to algorithms O(n) slower than if ArrayList was used.
  • Getting good performance is tricky.
  • Even when big-O performance is the same as ArrayList, it is probably going to be significant slower anyway.
  • It's jarring to see LinkedList in source because it is probably the wrong choice.
Tom Hawtin - tackline
Sorry. marked you down. LinkedList doesn't suck. There are situations where LinkedList is the correct class to use. I agree that there aren't many situations where it is better than an arraylist, but they do exist. Educate people who do silly things!
David Turner
Sorry to see you got lots of down-votes for this. There is indeed very little reason to use Java's LinkedList. In addition to the bad performance it also uses lots more memory than the other concrete List classes (every node has two additional pointers and each node is a separate wrapper object with the extra overhead bytes that go with them).
Kevin Brock
@Kevin I'm thick skinned enough to weather a few downvotes from stackoverflowers.
Tom Hawtin - tackline
This is one of the most useful answers here. It's a shame so many programmers fail to understand (a) the difference between abstract data types and concrete implementations, and (b) the real-world importance of constant factors and memory overhead in determining performance.
Porculus
+1  A: 

If your code has add(0) and remove(0), use a LinkedList and it's prettier addFirst() and removeFirst() methods. Otherwise, use ArrayList.

And of course, ImmutableList is your best friend.

Jesse Wilson
For small lists, ArrayList.add(0) is still always going to be faster than LinkedList.addFirst().
Porculus
+5  A: 

Yeah, I know, this is an ancient question, but I'll throw in my two cents:

LinkedList is almost always the wrong choice, performance-wise. There are some very specific algorithms where a LinkedList is called for, but those are very, very rare and the algorithm will usually specifically depend on LinkedList's ability to insert and delete elements in the middle of the list relatively quickly, once you've navigated there with a ListIterator.

There is one common use case in which LinkedList outperforms ArrayList: that of a queue. However, if your goal is performance, instead of LinkedList you should also consider using an ArrayBlockingQueue (if you can determine an upper bound on your queue size ahead of time, and can afford to allocate all the memory up front), or this CircularArrayList implementation. (Yes, it's from 2001, so you'll need to generify it, but I got comparable performance ratios to what's quoted in the article just now in a recent JVM)

Daniel Martin
+1 For that reference to CircularArrayList. This is a valuable part of my library.
Kevin Brock
+1  A: 

An important feature of a linked list (which I didn't read in another answer) is the concatenation of two lists. With an array this is O(n) (+ overhead of some reallocations) with a linked list this is only O(1) or O(2) ;-)

For the Java LinkedList this is not true. See this question.

Karussell
How is that? This may be true with linked list data structures but not a Java LinkList object. You can't just point a `next` from one list to the first node in the second list. The only way is to use `addAll()` which adds elements sequentially, though it is better than looping through and calling `add()` for each element. To do this quickly in O(1) you would need a compositing class (like org.apache.commons.collections.collection.CompositeCollection) but then this would work for any kind of List/Collection.
Kevin Brock
yes, true. I edited the answer accordingly. but see this answer for 'how' to do it with LinkedList: http://stackoverflow.com/questions/2494031/is-there-a-fast-concat-method-for-linked-list-in-java/2494884#2494884
Karussell
A: 
Algorithm     ArrayList   LinkedList
access front     O(1)         O(1)
access back      O(1)         O(1)
access middle    O(1)         O(N)
insert at front  O(N)         O(1)
insert at back   O(1)         O(1)
insert in middle O(N)         O(1)

http://leepoint.net/notes-java/algorithms/big-oh/bigoh.html

ArrayLists are good for write-once-read-many or appenders, but bad at add/remove from the front or middle.

Michael Munsey
You can't compare big-O values directly without thinking about constant factors. For small lists (and most lists are small), ArrayList's O(N) is faster than LinkedList's O(1).
Porculus
+1  A: 

An array list is essentially an array with methods to add items etc. (and you should use a generic list instead). It is a collection of items which can be accessed through an indexer (for example [0]). It implies a progression from one item to the next.

A linked list specifies a progression from one item to the next (Item a -> item b). You can get the same effect with an array list, but a linked list absolutely says what item is supposed to follow the previous one.

Kevin
+3  A: 

(note: might read a little oddly; that is because I merged a virtually identical .NET question; C# and Java are close enough that the concepts are identical)

Well, you should avoid ArrayList unless you are using .NET 1.1 (or micro-framework) - prefer typed collections like List<T> where possible.

The difference comes from the cost of traversal and manipulation. It is trivial to remove a node from the start or middle of a linked list, since you just re-link the nodes (likewise insert at any point). Removing an element from the start or middle of an array-backed list (including ArrayList and List<T>) involves copying all the elements above that point (as does inserting).

In both cases, inserting at the end is cheap (although the List<T> etc will occasionally have to resize the underlying array to make space, but it does this in a fairly sensible way).

If you just want to append, then use List<T> etc.

Marc Gravell