Difference Between ArrayList and LinkedList in Java
ArrayList and LinkedList both implement the List interface, so they offer the same methods and keep elements in insertion order. Their internals are completely different, which gives them very different performance:
ArrayListstores elements in a resizable array: instant access by index, but inserting or removing in the middle shifts elements.LinkedListstores elements in a doubly linked list of nodes: cheap insertion and removal at the ends (and at a known node), but access by index walks the list.
In practice, ArrayList is the right default for almost all code. This page explains why.
1. Comparison Table
| Aspect | ArrayList | LinkedList |
|---|---|---|
| Internal structure | Dynamic array | Doubly linked list of nodes |
get(i) / set(i) | O(1) | O(n) (walks from the nearer end) |
| Add at end | Amortised O(1) | O(1) |
| Add/remove at front | O(n) (shifts all elements) | O(1) |
| Add/remove in the middle | O(n) shift | O(n) to find the position, then O(1) relink (O(1) via an iterator) |
| Memory per element | One reference (plus spare capacity) | Node object with value, next and prev references (much more) |
| CPU cache friendliness | High (contiguous memory) | Low (nodes scattered in the heap) |
| Implements | List, RandomAccess | List, Deque |
| Null elements | Allowed | Allowed |
| Thread-safe | No | No |
2. Same API, Different Capabilities
import java.util.*;
public class ListBehaviour {
public static void main(String[] args) {
List<String> array = new ArrayList<>(List.of("B", "C", "D"));
LinkedList<String> linked = new LinkedList<>(List.of("B", "C", "D"));
// Same List API, same results
array.add(0, "A"); linked.add(0, "A");
array.remove("C"); linked.remove("C");
System.out.println("ArrayList : " + array + ", get(2) = " + array.get(2));
System.out.println("LinkedList: " + linked + ", get(2) = " + linked.get(2));
// LinkedList is also a Deque: cheap operations at both ends
linked.addFirst("start");
linked.addLast("end");
System.out.println("Deque ops : " + linked + ", pollFirst = " + linked.pollFirst() + ", peekLast = " + linked.peekLast());
System.out.println("RandomAccess? ArrayList " + (array instanceof RandomAccess)
+ ", LinkedList " + (linked instanceof RandomAccess));
}
}
ArrayList : [A, B, D], get(2) = D LinkedList: [A, B, D], get(2) = D Deque ops : [start, A, B, D, end], pollFirst = start, peekLast = end RandomAccess? ArrayList true, LinkedList false
Both lists produce identical results through the List interface. LinkedList additionally implements Deque, with methods like addFirst, pollFirst and peekLast.
3. Performance in Practice
A small benchmark with 100,000 elements:
import java.util.*;
public class ListBenchmark {
static long ms(Runnable r) { long s = System.nanoTime(); r.run(); return (System.nanoTime() - s) / 1_000_000; }
public static void main(String[] args) {
int n = 100_000;
List<Integer> array = new ArrayList<>(), linked = new LinkedList<>();
for (int i = 0; i < n; i++) { array.add(i); linked.add(i); }
long arrGet = ms(() -> { long sum = 0; for (int i = 0; i < 20_000; i++) sum += array.get(i * 5); });
long linkGet = ms(() -> { long sum = 0; for (int i = 0; i < 20_000; i++) sum += linked.get(i * 5); });
long arrFront = ms(() -> { for (int i = 0; i < 20_000; i++) array.add(0, i); });
long linkFront = ms(() -> { for (int i = 0; i < 20_000; i++) ((LinkedList<Integer>) linked).addFirst(i); });
System.out.printf("random get(i) x20k : ArrayList %4d ms | LinkedList %5d ms%n", arrGet, linkGet);
System.out.printf("insert at front x20k: ArrayList %4d ms | LinkedList %5d ms%n", arrFront, linkFront);
}
}
random get(i) x20k : ArrayList 0 ms | LinkedList 749 ms insert at front x20k: ArrayList 159 ms | LinkedList 0 ms
- Index-based access is dramatically slower on
LinkedList; afor (int i...) list.get(i)loop over it is O(n²). - Inserting at the front favours
LinkedList, butArrayDequedoes that even better. - For iteration and appending,
ArrayListis usually faster thanks to contiguous memory, even where big-O suggests a tie.
4. When to Use Which
- Use
ArrayListby default: reading by index, iterating, appending, sorting, typical business data. - Consider
LinkedListonly when you frequently insert or remove elements through an iterator in the middle of large lists, or need a list that is also a deque. - For queues and stacks, prefer
ArrayDeque, which is faster thanLinkedListand uses less memory.
5. Summary
ArrayListis array-backed: O(1) index access, O(n) insertions and removals in the middle or front.LinkedListis node-based: O(1) operations at the ends, O(n) index access, higher memory use.- Both implement
List;LinkedListalso implementsDeque. - Choose
ArrayListin almost all cases, andArrayDequefor queue-like use.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is the main difference between ArrayList and LinkedList?
ArrayList uses a dynamic array with fast index access; LinkedList uses a doubly linked list with fast insertion and removal at the ends.
Q2. Which is faster for get(index)?
ArrayList, at O(1). LinkedList must walk the nodes, which is O(n).
Q3. Which is faster for adding elements?
At the end both are fast, and ArrayList is usually faster in practice. At the front, LinkedList wins.
Q4. Which uses more memory?
LinkedList: every element needs a node object with two extra references.
Q5. Is LinkedList better for removing elements?
Only when removing through an iterator or at the ends. remove(index) still has to find the node first.
Q6. Do both maintain insertion order?
Yes. Both are ordered lists that allow duplicates and nulls.
Q7. Are they thread-safe?
No. Wrap with Collections.synchronizedList, or use CopyOnWriteArrayList or concurrent queues.
Q8. Can LinkedList be used as a queue?
Yes, it implements Deque. However, ArrayDeque is usually the better queue or stack implementation.
Q9. What is the RandomAccess interface?
A marker indicating fast index access. ArrayList implements it; LinkedList does not, so algorithms can choose iterators for it.
Q10. How does ArrayList grow?
By creating an array about 1.5 times larger and copying the elements, which makes appends amortised O(1).
Q11. Why is ArrayList usually faster even for insertions?
Shifting a contiguous array uses fast memory copies and is cache-friendly, while linked lists suffer cache misses and object allocation.
Q12. Which should I use by default?
ArrayList.
Q13. Can both store null?
Yes, any number of nulls.
Q14. Do both support ListIterator?
Yes. A ListIterator on a LinkedList allows O(1) insertion and removal at its current position.
Q15. Which is better for sorting?
Both are sorted by copying into an array internally; ArrayList sorts in place with less overhead.
Q16. Is LinkedList a singly or doubly linked list?
Doubly linked: each node references both its previous and next node.
Q17. Why is iterating LinkedList with get(i) slow?
Each get(i) walks from an end, so the loop becomes O(n²). Use a for-each loop or iterator instead.
Q18. What is the initial capacity of each?
ArrayList starts with capacity 10 (allocated on first add). LinkedList has no capacity concept.
Q19. Do they have the same methods?
They share all List methods; LinkedList adds Deque methods and ArrayList adds ensureCapacity and trimToSize.
Q20. Is this asked in interviews?
Very often. Discuss internals, time complexity, memory, cache effects and why ArrayList is the usual choice.