collections
beginnerArrayList vs LinkedList
Pick the list backed by an array (fast random access) or by a doubly-linked list (fast insert/remove at known nodes).
Both ArrayList and LinkedList hold a list of items. They store those items very differently. ArrayList keeps them side by side in one block of memory, like seats in a row. LinkedList scatters them, and each item holds the address of the next and previous one.
ArrayList = a bookshelf with numbered slots (instantly grab #7). LinkedList = a paper chain (snip and rejoin links easily, but counting to the 7th link takes time).
Key Concepts
1
That difference decides which is faster, and the answer is not the one the textbook table suggests.
2
This is the question that catches people who learned data structures from a table rather
than from a machine. On paper LinkedList wins at insertion; in practice ArrayList wins almost
everywhere, and explaining why is the whole point of the question.
LinkedListArrayList
3
The structures. ArrayList holds a contiguous Object[] and grows by allocating a larger array —
1.5x in the OpenJDK implementation — and copying. LinkedList is a doubly-linked chain of nodes, each
holding an element reference plus two node references.
ArrayListObject[]LinkedList
4
Memory is the first surprise. An ArrayList slot costs one reference: 4 bytes with compressed oops.
A LinkedList node costs an object header (16 bytes) plus three references (12 bytes) = ~32-40 bytes per
element, eight to ten times more. For a million Integer elements that is roughly 4 MB against 40 MB
before counting the boxed values themselves.
ArrayListLinkedListInteger
5
Cache locality is the second, and it dominates. Array elements sit together, so walking one pulls the
next several into the CPU cache line for free. Linked nodes are scattered across the heap, so each step is
a potential cache miss costing ~100 ns against ~1 ns for an L1 hit. Iterating a large LinkedList can be
an order of magnitude slower than the same ArrayList even though both are "O(n)".
LinkedListArrayList
6
The theoretical advantage almost never applies. LinkedList.add(index, e) is O(1) *once you hold the
node*, but reaching index i is O(n) traversal, so insertion in the middle is O(n) overall — the same as
ArrayList's shift, except ArrayList's shift is System.arraycopy, an intrinsic that moves contiguous
memory far faster than pointer chasing. The genuine wins are insertion at the ends and removal through an
iterator you already hold.
LinkedList.add(index, e)iArrayListSystem.arraycopy
7
ArrayList has one cost worth naming: growth copies. Adding a million elements from an empty list
triggers around 30 reallocations and copies ~2 million element slots in total. new ArrayList<>(expected)
removes it, which is the same pre-sizing argument as HashMap.
ArrayListnew ArrayList<>(expected)HashMap
8
What to answer when asked which to use. ArrayList by default. ArrayDeque if you need a queue or
stack — it beats LinkedList at both. LinkedList when you genuinely need Deque semantics and removal
via iterator in the middle of a large structure, which is rare enough that many codebases have none.
ArrayListArrayDequeLinkedListDeque
9
What the interviewer is probing.1. "Which is faster for insertion?" Probing: whether you repeat the table or reason about machines.
Stalls: "LinkedList, it's O(1)." Moves up: O(1) only with the node in hand; finding the position is
O(n), and arraycopy beats pointer chasing.
arraycopy
10
2. "Why is iteration slower on LinkedList?" Probing: cache behaviour. Stalls: "It's the same
complexity." Moves up: scattered nodes cause cache misses — ~100 ns versus ~1 ns per step.
11
3. "How much more memory?" Probing: concrete numbers. Stalls: "A bit more." Moves up: ~32-40
bytes per node against 4 bytes per array slot, so ~10x for the structure itself.
12
4. "When would you actually pick LinkedList?" Probing: honesty. Stalls: "For frequent inserts."
Moves up: rarely — ArrayDeque covers queue and stack use; LinkedList fits iterator-based removal in a
large list.
ArrayDequeLinkedList
13
5. "How does ArrayList grow?" Probing: the amortised cost. Stalls: "It doubles." Moves up: 1.5x
in OpenJDK; ~30 reallocations reaching a million, avoidable by pre-sizing.
14
Cost per element (64-bit JVM, compressed oops)15
ArrayList slot reference 4 B
LinkedList node header 16 + item 4 + prev 4
+ next 4 28-32 B
(aligned) ~32-40 B16
1,000,000 elements ArrayList structure ~4 MB
LinkedList structure ~32-40 MB17
Operation costs, and what actually happens18
Operation ArrayList LinkedList
------------------------------------------------------------------
get(i) O(1) O(n) traversal
add(e) at end O(1) amortised O(1)
add(0, e) O(n) arraycopy O(1)
add(mid, e) O(n) arraycopy O(n) to find + O(1)
remove via iterator O(n) shift O(1)
contains(e) O(n) O(n), cache-hostile
Iteration sequential memory pointer chasing19
Growth cost, empty ArrayList to 1,000,000 elements
growth factor 1.5x (OpenJDK)
reallocations ~30
total slots copied ~2,000,000
with new ArrayList<>(1_000_000) 020
Rule of thumb
Default to ArrayList. Need a queue or stack -> ArrayDeque.
LinkedList only for Deque semantics plus iterator removal.