Listsmedium0-2 years

"ArrayList or LinkedList?" — a teammate picks LinkedList because the service inserts into a list a lot and the textbook says LinkedList is O(1) for insertion. What's actually true about that, and what should they use instead?

The textbook is only right about insertion at a position you're already holding — the head, the tail, or through an iterator you already have. add(index, e) on a LinkedList isn't O(1) in practice, because reaching index i means walking the chain from one end, node by node, which is O(n) before the O(1) insertion even happens; the same is true in reverse for ArrayList's add(index, e), which shifts every element after it with arraycopy, but that shift is one tight, contiguous memory copy that runs at memory bandwidth, and it beats a pointer-chasing walk by a wide margin in real measurements. ArrayList wins almost every benchmark that looks like "insert a lot," including most insertion-heavy ones, because the constant factor the textbook's Big-O ignores — cache-friendly contiguous memory versus scattered nodes and pointer chases — dominates at realistic sizes. The one place the textbook is actually right is inserting or removing at the very front repeatedly, and even there ArrayDeque, a ring buffer, beats LinkedList at its own specialty.

The lesson behind it →