The full picture
| Operation | ArrayList | LinkedList | Reality check |
|---|---|---|---|
| get(i) | O(1) | O(n) | no contest |
| add at end | O(1) amortized | O(1) | ArrayList still wins — no node allocation |
| insert middle | O(n) shift | O(n) traverse + O(1) link | System.arraycopy is vectorized; ArrayList often wins anyway |
| memory/element | ~4–8 bytes ref | ~40+ bytes (node + 2 refs + header) | LinkedList also scatters nodes → cache misses |
The senior takeaway: mechanical sympathy. CPUs prefetch contiguous memory; an ArrayList scan streams through cache lines, while a LinkedList chases pointers to random heap addresses. Legitimate LinkedList niches are rare — it's a decent Deque, but ArrayDeque beats it there too. If you're inserting/removing heavily at both ends or mid-iteration, consider ArrayDeque, or re-think the algorithm (often a different data structure — ring buffer, gap buffer, or just collect-then-rebuild — is the real answer).