|
| 1 | +# Internal Working of LinkedList |
| 2 | + |
| 3 | +This document explains how `java.util.LinkedList` works internally from a data-structure perspective. |
| 4 | + |
| 5 | +It covers the **theory, internal representation, working of core operations with ASCII examples, complexity analysis, |
| 6 | +memory layout, iteration semantics, concurrency notes, tuning tips, and debugging points**. |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## Overview |
| 11 | + |
| 12 | +- `LinkedList` is a **doubly linked list** implementation of `List` and `Deque`. |
| 13 | +- Built from `Node` objects linked via `prev` and `next`. |
| 14 | +- Tracks: |
| 15 | + - `first` → head node |
| 16 | + - `last` → tail node |
| 17 | + - `size` → number of elements |
| 18 | +- **Strengths:** cheap insertions/removals at ends or via iterators. |
| 19 | +- **Weaknesses:** slower random access than `ArrayList`. |
| 20 | + |
| 21 | +--- |
| 22 | + |
| 23 | +## Conceptual Node Structure |
| 24 | + |
| 25 | +```java |
| 26 | +static class Node<E> { |
| 27 | + E item; // stored value |
| 28 | + Node<E> next; // reference to next node |
| 29 | + Node<E> prev; // reference to previous node |
| 30 | +} |
| 31 | +``` |
| 32 | + |
| 33 | +Each node knows: |
| 34 | + |
| 35 | +- Its **value** (`item`). |
| 36 | +- Its **previous neighbor** (`prev`). |
| 37 | +- Its **next neighbor** (`next`). |
| 38 | + |
| 39 | +--- |
| 40 | + |
| 41 | +## Visual Representation |
| 42 | + |
| 43 | +Empty list: |
| 44 | + |
| 45 | +``` |
| 46 | +first -> null |
| 47 | +last -> null |
| 48 | +size = 0 |
| 49 | +``` |
| 50 | + |
| 51 | +List with [A, B, C]: |
| 52 | + |
| 53 | +``` |
| 54 | +null <- [A] <-> [B] <-> [C] -> null |
| 55 | + ^first ^last |
| 56 | +size = 3 |
| 57 | +``` |
| 58 | + |
| 59 | +For node [B]: `prev → [A]`, `next → [C]`. |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +## Core Operations |
| 64 | + |
| 65 | +### Append (`add` / `addLast`) |
| 66 | + |
| 67 | +- Creates a new node at the tail. |
| 68 | +- Steps: |
| 69 | + 1. `newNode = new Node(last, e, null)`. |
| 70 | + 2. If empty → `first = newNode`. |
| 71 | + 3. Else link `last.next = newNode` and update `last`. |
| 72 | +- Complexity: **O(1)**. |
| 73 | + |
| 74 | +ASCII Example: |
| 75 | + |
| 76 | +``` |
| 77 | +Before: [A] <-> [B] |
| 78 | +After add(C): [A] <-> [B] <-> [C] |
| 79 | +``` |
| 80 | + |
| 81 | +--- |
| 82 | + |
| 83 | +### Prepend (`addFirst`) |
| 84 | + |
| 85 | +- Creates a new node at the head. |
| 86 | +- Steps: |
| 87 | + 1. `newNode = new Node(null, e, first)`. |
| 88 | + 2. If empty → `last = newNode`. |
| 89 | + 3. Else link `first.prev = newNode` and update `first`. |
| 90 | +- Complexity: **O(1)**. |
| 91 | + |
| 92 | +ASCII Example: |
| 93 | + |
| 94 | +``` |
| 95 | +Before: [B] <-> [C] |
| 96 | +After addFirst(A): [A] <-> [B] <-> [C] |
| 97 | +``` |
| 98 | + |
| 99 | +--- |
| 100 | + |
| 101 | +### Insert at Index (`add(i, e)`) |
| 102 | + |
| 103 | +- Traverses from nearest end using `node(index)`. |
| 104 | +- Inserts between neighbors. |
| 105 | +- Complexity: **O(n)**. |
| 106 | + |
| 107 | +ASCII Example: |
| 108 | + |
| 109 | +``` |
| 110 | +Before: [A] <-> [C] |
| 111 | +Insert X at index 1: [A] <-> [X] <-> [C] |
| 112 | +``` |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +### Access (`get(i)` / `set(i, e)`) |
| 117 | + |
| 118 | +- Traverses from closest end to reach node. |
| 119 | +- Complexity: **O(n)**. |
| 120 | + |
| 121 | +ASCII Example (`get(2)`): |
| 122 | + |
| 123 | +``` |
| 124 | +[A] <-> [B] <-> [C] <-> [D] |
| 125 | +Traversal path: first -> A -> B -> C |
| 126 | +``` |
| 127 | + |
| 128 | +--- |
| 129 | + |
| 130 | +### Removal (`remove(i)` / `remove(Object o)`) |
| 131 | + |
| 132 | +- Locates target, unlinks from neighbors, nulls references. |
| 133 | +- Complexity: **O(n)**, except head/tail removals: **O(1)**. |
| 134 | + |
| 135 | +ASCII Example: |
| 136 | + |
| 137 | +``` |
| 138 | +Before: [A] <-> [X] <-> [B] <-> [C] |
| 139 | +remove(2): unlink B |
| 140 | +After: [A] <-> [X] <-> [C] |
| 141 | +``` |
| 142 | + |
| 143 | +--- |
| 144 | + |
| 145 | +## Iteration |
| 146 | + |
| 147 | +- `ListIterator` supports forward/backward traversal. |
| 148 | +- Iterator `add` / `remove` → **O(1)**. |
| 149 | +- **Fail-fast:** throws `ConcurrentModificationException` on structural change outside iterator. |
| 150 | + |
| 151 | +ASCII Example (iteration): |
| 152 | + |
| 153 | +``` |
| 154 | +Start -> [A] -> [B] -> [C] -> End |
| 155 | +Iterator moves along nodes. |
| 156 | +``` |
| 157 | + |
| 158 | +--- |
| 159 | + |
| 160 | +## Memory Layout & GC |
| 161 | + |
| 162 | +- Each node = object header + 3 references + element. |
| 163 | +- Higher overhead than `ArrayList` due to per-node object. |
| 164 | +- After removal, sets `item`, `prev`, and `next` = `null` → helps GC. |
| 165 | + |
| 166 | +--- |
| 167 | + |
| 168 | +## ⚡ Complexity Summary |
| 169 | + |
| 170 | +| Operation | Time Complexity | Notes | |
| 171 | +| -------------------------------- | --------------- | ------------------------------------ | |
| 172 | +| `get(index)` | O(n) | Traverses \~half of list on average. | |
| 173 | +| `set(index, e)` | O(n) | Must locate node first. | |
| 174 | +| `add(e)` / `addLast(e)` | O(1) | Tail insertion. | |
| 175 | +| `addFirst(e)` | O(1) | Head insertion. | |
| 176 | +| `add(index, e)` | O(n) | Traversal + insertion. | |
| 177 | +| `removeFirst()` / `removeLast()` | O(1) | Direct head/tail removal. | |
| 178 | +| `remove(index)` | O(n) | Traversal needed. | |
| 179 | +| `contains(e)` / `indexOf(e)` | O(n) | Linear search. | |
| 180 | + |
| 181 | +✅ **Rule of thumb:** Use `LinkedList` for **fast head/tail ops** & iterator-based changes; |
| 182 | +avoid for frequent random access. |
| 183 | + |
| 184 | +--- |
| 185 | + |
| 186 | +## Concurrency |
| 187 | + |
| 188 | +- Not synchronized → requires external sync. |
| 189 | +- Alternatives: `ConcurrentLinkedDeque`, `ConcurrentLinkedQueue`. |
| 190 | + |
| 191 | +--- |
| 192 | + |
| 193 | +## Practical Guidance |
| 194 | + |
| 195 | +**Use when:** |
| 196 | + |
| 197 | +- Frequent head/tail insertions/removals. |
| 198 | +- Heavy iterator use. |
| 199 | + |
| 200 | +**Avoid when:** |
| 201 | + |
| 202 | +- Random access is common (→ prefer `ArrayList`). |
| 203 | +- Memory overhead is critical. |
| 204 | + |
| 205 | +--- |
| 206 | + |
| 207 | +## Performance & Debugging Tips |
| 208 | + |
| 209 | +- Avoid `get(i)` in loops → O(n^2) trap. |
| 210 | +- Use iterators or for-each. |
| 211 | +- Profile allocations for large lists. |
| 212 | +- For concurrency, consider `CopyOnWriteArrayList` or concurrent queues. |
| 213 | + |
| 214 | +--- |
| 215 | + |
| 216 | +## Extended Visual Examples |
| 217 | + |
| 218 | +1. **Start empty → addFirst(A) → addLast(B) → addLast(C):** |
| 219 | + |
| 220 | +``` |
| 221 | +[A] |
| 222 | +[A] <-> [B] <-> [C] |
| 223 | +``` |
| 224 | + |
| 225 | +2. **add(1, X) on [A, B, C]:** |
| 226 | + |
| 227 | +``` |
| 228 | +[A] <-> [X] <-> [B] <-> [C] |
| 229 | +``` |
| 230 | + |
| 231 | +3. **remove(2) on [A, X, B, C] → remove B:** |
| 232 | + |
| 233 | +``` |
| 234 | +[A] <-> [X] <-> [C] |
| 235 | +``` |
| 236 | + |
| 237 | +4. **Iterator insertion at index 1 (on [A, C]):** |
| 238 | + |
| 239 | +``` |
| 240 | +Before: [A] <-> [C] |
| 241 | +Iterator add(B): [A] <-> [B] <-> [C] |
| 242 | +``` |
| 243 | + |
| 244 | +--- |
| 245 | + |
| 246 | +## FAQ |
| 247 | + |
| 248 | +- **Q:** Does it implement `Deque`? → **Yes.** |
| 249 | +- **Q:** Is it thread-safe? → **No.** External sync required. |
| 250 | +- **Q:** Better than `ArrayList`? → **Depends on workload.** |
| 251 | + |
| 252 | +--- |
0 commit comments