Java tutorials > Core Java Fundamentals > Data Structures and Collections > When to use `ArrayList` vs `LinkedList`?
When to use `ArrayList` vs `LinkedList`?
Choosing between `ArrayList` and `LinkedList` in Java depends heavily on how you intend to use the list. Both implement the `List` interface, but their underlying implementations differ significantly, leading to different performance characteristics. This tutorial explores these differences to help you make informed decisions.
Underlying Data Structures
ArrayList: Based on a dynamically resizing array. Elements are stored in contiguous memory locations. This provides fast random access (getting an element by its index) but can be slow for insertions or deletions in the middle of the list because elements may need to be shifted.
LinkedList: Based on a doubly linked list. Each element (node) contains a value and pointers to the next and previous elements. This allows for fast insertions and deletions in the middle of the list but slower random access because you need to traverse the list to find a specific element.
Time Complexity Comparison
Understanding the time complexity of common operations is crucial for choosing the right data structure:
ArrayList:
LinkedList:
When to Use ArrayList
Choose `ArrayList` when:
When to Use LinkedList
Choose `LinkedList` when:
Code Snippet: Adding Elements
This code demonstrates adding elements to both `ArrayList` and `LinkedList`. Notice the `add(index, element)` method, which inserts an element at a specific index. This is where `LinkedList` can potentially outperform `ArrayList` if insertions are frequent.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListComparison {
public static void main(String[] args) {
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
// Adding elements
arrayList.add("Apple");
arrayList.add("Banana");
arrayList.add(1, "Orange"); // Insert at index 1
linkedList.add("Apple");
linkedList.add("Banana");
linkedList.add(1, "Orange"); // Insert at index 1
System.out.println("ArrayList: " + arrayList);
System.out.println("LinkedList: " + linkedList);
}
}
Code Snippet: Retrieving Elements
This code demonstrates retrieving elements from both `ArrayList` and `LinkedList` using the `get(index)` method. `ArrayList` excels here due to its O(1) time complexity.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListComparison {
public static void main(String[] args) {
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
arrayList.add("Apple");
arrayList.add("Banana");
arrayList.add("Orange");
linkedList.add("Apple");
linkedList.add("Banana");
linkedList.add("Orange");
// Retrieving elements
String arrayListElement = arrayList.get(1);
String linkedListElement = linkedList.get(1);
System.out.println("ArrayList element at index 1: " + arrayListElement);
System.out.println("LinkedList element at index 1: " + linkedListElement);
}
}
Real-Life Use Case Section
ArrayList: Imagine managing a list of products in an e-commerce application. You often need to access a product by its ID (index) quickly. `ArrayList` is suitable here because you frequently need random access and additions/removals are less frequent.
LinkedList: Consider implementing an undo/redo functionality in a text editor. Each action is a node in a linked list. When a user undoes, you remove the last node. When they redo, you add it back. `LinkedList` is a good choice for this scenario because you frequently insert and delete at the beginning or end of the list.
Best Practices
Interview Tip
When asked about `ArrayList` vs `LinkedList` in an interview, focus on their underlying implementations, time complexities of common operations, and scenarios where each is more suitable. Emphasize that the choice depends on the specific use case and that profiling can be helpful for performance-critical applications.
Memory footprint
ArrayList: Generally more memory-efficient if you know the approximate size of the list beforehand because it stores elements contiguously. However, if the `ArrayList` needs to resize frequently, it can lead to memory overhead due to creating new, larger arrays and copying data.
LinkedList: Requires more memory per element because it stores pointers to the next and previous nodes. However, it doesn't need to resize, so it avoids the memory overhead associated with `ArrayList` resizing.
Alternatives
Pros of ArrayList
Cons of ArrayList
Pros of LinkedList
Cons of LinkedList
FAQ
-
Which is faster for adding elements to the end of the list?
`ArrayList` is generally faster for adding elements to the end due to amortized O(1) time complexity. `LinkedList` also has O(1) complexity for adding to the end, but the overhead of creating a new node can sometimes make it slightly slower. However, the difference is usually negligible. -
When should I use `LinkedList`?
Use `LinkedList` when you need frequent insertions and deletions, especially in the middle of the list, and random access is not a primary requirement. Also, it's a good choice for implementing queues and deques. -
When should I use `ArrayList`?
Use `ArrayList` when you need frequent random access to elements by index, and insertions and deletions are less frequent or primarily at the end of the list. -
Are `ArrayList` and `LinkedList` thread-safe?
No, neither `ArrayList` nor `LinkedList` are inherently thread-safe. If you need thread-safe list operations, consider using `CopyOnWriteArrayList` (for read-heavy scenarios) or synchronizing access to the list using `Collections.synchronizedList()`.