January 24, 2004

LinkedList vs. ArrayList performance tests

I always thought using LinkedList was a good idea for lists that I was only going to add (to the end of) to and iterate over, since there would be no overhead for allocating arrays larger than I needed. I ran some tests and found that for simple adding and iterating, ArrayList is almost always faster, no matter what the list's initial size is.

(I use lists in this way when building arrays that need to be passed or stored somewhere as arrays.)

I ran tests adding elements to the end of to thousands of lists, and then different tests iterating over those lists. I used thousands of lists to counteract any kind of significant overhead as well as timing resolution errors.

My tests found that appending items to an ArrayList is always at least twice as fast than adding items to a LinkedList, no matter what the ArrayList's initial size is.

My tests found that iterating over either list type (using an Iterator) has similar performance, but ArrayList wins for smaller data sets. LinkedList's iteration performance increases slightly as the number of elements increases, while ArrayList's performance decreases slightly.

So really, if you're just adding to the end and iterating (like with a list of listeners, or a temporary list that's going to be converted to an array), it's probably best to use ArrayList.

UPDATE 10:30PM: I made it clearer that I was only testing adding to the end of lists, not in the middle.

Posted by keith at January 24, 2004 08:15 PM | TrackBack
Comments

Mate,

LinkedLists are only to be used where you are doing inserts (rather than adds). Inserts into the middle of an arraylist means that you need to copy the rest of the array (move it by one).

With linked lists, it is a constant operation.

Try arrays with millions of elements to see the difference.

Posted by: Scott Farquhar at January 24, 2004 08:58 PM

Yeah, I understand that part. I'm talking about lists where I only add to the end, and then iterate. I use these when building arrays. I'll update the entry to make that clearer.

Posted by: Keith Lea at January 24, 2004 10:35 PM

The size of the array counts.

In an ArrayList, the default size is 10 elements. Whenever it needs to grow, it doubles (from memory); I'm not sure when it shrinks.

Every time it changes size, it needs to copy all the elements of the underlying array to the new one. This takes time. However, if it doesn't need to grow, then adding an element is nice and fast; it's just an array allocation.

If you have to build the array from scratch, without knowing the length in advance, AND the list is long (in the millions), the linked list will be faster. But, by and large, growing an array list will normally be faster, especially if you can pre-size it.

(BTW, if your major use is to turn the ArrayList into an array, I suggest you check out the toArray() method on the List interface, rather than iterating)

Posted by: Robert Watkins at January 25, 2004 03:56 AM

>If you have to build the array from scratch, without knowing the length in advance, AND the list is long (in the millions), the linked list will be faster. But, by and large, growing an array list will normally be faster, especially if you can pre-size it.

WRONG!!

Even if you build the array from scratch, it is still likely to be faster than using the linked list. First, both arraylists and linked list adds are constant-time; second, array usually considerably less memory without the minimum 12-byte object overhead for each linked list node; third, array entries are localized and thus easier on the cache; linked lists caused the garbage collection to do far more object tracking.

First of all, although a single add operation can take time proportional to the number of elements, overall when you amortize the cost of the add operation over the lifetime of the array, the add operation takes on average constant time. If you have taken a data structures class, you know that a dynamic array is only twice as slow as a preallocated array, because when you finally add n elements, the maximum number of copies you will have made is n.

Jim Gray has a good article where he analyzed the performance of linked lists and arrays; and showed that arraylists were much faster for larger number of elements because of locality.

Posted by: Wesner Moise at January 25, 2004 06:41 AM

Also, the default capacity of an arraylist is 16 objects. The ArrayList never shrinks, so you must call TrimToSize to explicit shrink the list.

Posted by: Wesner Moise at January 25, 2004 06:44 AM

Wesner: Not quite. From the J2SE javadocs for ArrayList:

The add operation runs in amortized constant time, that is, adding n elements requires O(n) time.

Adding to an ArrayList can never be considered constant time, because eventually the underlying array must grow. This is where the "amortized" comes in. You pay a single high cost when the array needs to grow, while the other inserts are low cost O(1). Ultimately, the average cost of adding to an ArrayList, as Sun states, is O(n).

LinkedList, however, is guaranteed to be O(1) for adds and something similarly small for inserts (maybe O(log n)?). The point to keep in mind is that for small lists, LinkedList's O(1) is going to be larger than ArrayList's O(n) because LinkedList has much more object creation overhead. For large lists, however, adding the millionth element to an ArrayList with an array of 999,999 slots is going to be far slower than adding the same millionth element to a LinkedList.

Posted by: Charles Nutter at January 27, 2004 10:58 AM

That's not what my benchmarks found, Charles. LinkedList's performance decreased as N increased, possibly due to the fact that it allocates so much more memory than ArrayList does.

Posted by: Keith Lea at January 27, 2004 11:39 AM

There's a fine line between genius and insanity. I have erased this line.

Posted by: Blackman Mark at May 2, 2004 02:31 PM

A person never tells you anything until contradicted.

Posted by: Friedman Joseph at May 3, 2004 03:13 AM

what do you mean?

Posted by: Tom Gallus at May 19, 2004 07:51 PM

I can't understand why a person will take a year to write a novel when he can easily buy one for a few dollars.

Posted by: GernerMathisen Aina at June 30, 2004 08:44 AM

NUDE PHOTOS

Posted by: NUDE-PHOTOS at July 28, 2004 07:35 PM

Hello!

My Tests showed, that adding elements to a LinkedList results in better performance compared to ArrayList. (by factor 1.5). This comes clear when looking to to add() operation of both classes:

Addin in LinkedList:
private Entry addBefore(Object o, Entry e) {
Entry newEntry = new Entry(o, e, e.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}

Adding in ArrayList:

modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = (Object[])ExtendedSystem.resizeArray(newCapacity,
elementData,
0,
size); /*SHIRAZ*/
}
elementData[size++] = o;

Posted by: Johannes Marchart at August 27, 2004 03:55 AM
Post a comment