🔗 ArrayList vs LinkedList — Quick Summary
| Feature | ArrayList | LinkedList |
|---|
| Internal Structure | Resizable array | Doubly linked list (nodes point to next & previous) |
| Access Time (get(index)) | ✅ Fast (O(1)) — direct access by index | ❌ Slow (O(n)) — traverse from head/tail |
| Insertion (add to end) | ✅ Fast (usually amortized O(1)) | ✅ Fast (O(1)) when adding to end |
| Insertion (add to middle) | ❌ Slow (O(n)) — shift elements | ✅ Fast (O(1) once position found) |
| Deletion (remove at index) | ❌ Slow (O(n)) — shift elements | ✅ Fast (O(1) once position found) |
| Memory Overhead | ✅ Lower (just array storage) | ❌ Higher (each node holds data + 2 pointers) |
| Iteration | ✅ Cache-friendly (elements in contiguous memory) | ❌ Cache-unfriendly (nodes scattered in memory) |
| When to Use? | Frequent random access (read-heavy apps) | Frequent inserts/removals (write-heavy apps) |
📦 Internal Representation
🧱 ArrayList (Resizable Array)
ArrayList uses a contiguous array under the hood.- When the array is full, it resizes (usually doubles in size) and copies old elements into a new array.
Example structure:
🔗 LinkedList (Doubly Linked List)
LinkedList uses nodes — each node stores:- Data
- Pointer to next node
- Pointer to previous node
Example structure:
HEAD → [A] ↔ [B] ↔ [C] ↔ [D] → TAIL
⏱️ Time Complexity Comparison
| Operation | ArrayList | LinkedList |
|---|
| Add to end | Amortized O(1) | O(1) |
| Add to front | O(n) (shift everything) | O(1) |
| Add to middle | O(n) (shift elements) | O(n) (traverse to position) |
| Remove from end | O(1) | O(1) |
| Remove from front | O(n) (shift elements) | O(1) |
| Remove from middle | O(n) | O(n) |
| Get by index | O(1) | O(n) (must traverse list) |
🔥 Real-World Usage Recommendations
| Case | Best Choice |
|---|
| Fast random access (get by index) | ✅ ArrayList |
| Read-heavy collections (searching, lookups) | ✅ ArrayList |
| Frequent insertion/removal in the middle | ✅ LinkedList |
| Frequent insertion/removal at head/tail | ✅ LinkedList |
| Memory efficiency is important | ✅ ArrayList (less overhead per element) |
💻 Code Examples
ArrayList Example (Fast Random Access)
List<String> list = new ArrayList<>();
list.add("Alice");
list.add("Bob");
System.out.println(list.get(1)); // Fast O(1)
LinkedList Example (Efficient Insertion/Removal at Head)
List<String> list = new LinkedList<>();
list.add("Alice");
list.add(0, "Bob"); // Inserting at head is fast in LinkedList
System.out.println(list);
🏁 Final Verdict (When to Use What)
| Use Case | Recommended Collection |
|---|
| Data mostly read by index | ArrayList |
| Data frequently inserted/removed at head/middle | LinkedList |
| Data size is small and memory matters | ArrayList |
| Large data set with frequent insertions/removals in middle | LinkedList (but only if performance tests prove the need!) |
⚠️ Note — In Modern Java
ArrayList is preferred in most cases because:- Faster access.
- Better CPU cache utilization (contiguous array in memory).
- Even insertion/removal (except head/middle) is pretty fast for moderate list sizes.
LinkedList is rarely the best choice unless you have very specialized needs (like writing your own LRU cache).