🔗 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).