List
The List interface — ordered, indexed, allows duplicates. When to use ArrayList vs LinkedList, and the patterns senior developers rely on.
Last reviewed: January 2025
🔍 What Is It?
List Interface
java.util.List extends Collection and adds:
- →get(int index) — access by position
- →set(int index, E element) — replace at position
- →add(int index, E element) — insert at position
- →remove(int index) — remove at position
- →indexOf(Object o) — find first occurrence
- →subList(int from, int to) — view of a portion
- →listIterator() — bidirectional iteration
Key Implementations:
- →ArrayList — resizable array; O(1) random access; O(n) insert/delete in middle
- →LinkedList — doubly-linked list; O(n) random access; O(1) insert/delete at known position; also implements Deque
- →Vector — legacy synchronized ArrayList; avoid in new code
- →CopyOnWriteArrayList — thread-safe; creates copy on every write; best for read-heavy concurrent access
- →List.of() — immutable list (Java 9+); throws UnsupportedOperationException on modification
- →Arrays.asList() — fixed-size list backed by array; allows set() but not add/remove
🎯 Why Do We Need It?
Lists solve ordered collection needs:
- →Ordered data — results from a database query, items in a shopping cart, steps in a workflow
- →Index access — pagination (get items 20-40), random sampling
- →Duplicates allowed — unlike Set, List allows the same element multiple times
- →Iteration order guaranteed — elements always come out in insertion order
In enterprise Java, List is the most commonly used collection type — most service methods return List<SomeEntity>.
🏗️ What Happens in Real Projects?
Common patterns in enterprise code:
// Service returns List
public List<Order> getOrdersByCustomer(String customerId) {
return orderRepository.findByCustomerId(customerId);
}
// Immutable list for constants
private static final List<String> VALID_CURRENCIES = List.of("USD", "EUR", "GBP");
// Defensive copy to prevent external modification
public List<LineItem> getLineItems() {
return Collections.unmodifiableList(lineItems);
}
// Sorting
orders.sort(Comparator.comparing(Order::getCreatedAt).reversed());⚙️ How It Works
ArrayList Internals:
- →Backed by an Object[] array
- →Initial capacity: 10
- →When full, creates new array 1.5x the size and copies elements
- →This resize is O(n) but happens rarely — amortized O(1) add
- →Random access: O(1) — direct array index
- →Insert/delete in middle: O(n) — must shift elements
LinkedList Internals:
- →Each element is a Node with prev and next pointers
- →No array — no resizing
- →Random access: O(n) — must traverse from head
- →Insert/delete at known position: O(1) — just update pointers
- →Higher memory overhead: each node has two extra references
💻 Example
List Patterns in Enterprise Code — The List operations you use in every Java project.
🤔 Common Confusions
❓ When should I use LinkedList instead of ArrayList?
Almost never in practice. LinkedList is theoretically faster for insert/delete at the beginning, but the cache locality of ArrayList makes it faster in practice for almost all real workloads. LinkedList also uses more memory (two pointers per node). Use LinkedList only if you are implementing a queue/deque and need O(1) add/remove from both ends — and even then, ArrayDeque is usually better.
❓ What is the difference between List.of() and Arrays.asList()?
List.of() (Java 9+) returns a truly immutable list — you cannot add, remove, or set elements, and it does not allow null values. Arrays.asList() returns a fixed-size list backed by the array — you can set() elements but cannot add() or remove(). Also, Arrays.asList() allows null. Use List.of() for constants and return values you want to protect.
❓ Does Collections.sort() modify the original list?
Yes. Collections.sort() and list.sort() sort the list in-place. If you need a sorted copy without modifying the original, use: List<T> sorted = list.stream().sorted().collect(Collectors.toList()); or new ArrayList<>(list) then sort the copy.
🚨 Common Production Issues
ConcurrentModificationException — modifying a list while iterating it with for-each throws this. Use Iterator.remove(), removeIf(), or collect to a new list.
Returning mutable internal lists — callers can add/remove from your internal state. Return Collections.unmodifiableList() or a copy.
ArrayList with known large size — if you know the list will hold 10,000 items, initialize with new ArrayList<>(10000) to avoid 10+ resize operations.
Using List.subList() and then modifying the parent — subList is a view; modifying the parent list while holding a subList reference causes ConcurrentModificationException.
✅ Best Practices
Use ArrayList as the default List implementation — it is the right choice for 95% of use cases.
Declare variables as List<T>, not ArrayList<T> — program to the interface.
Use List.of() for immutable lists (constants, return values you want to protect).
Use removeIf() instead of iterating and removing — cleaner and avoids ConcurrentModificationException.
Initialize ArrayList with expected capacity when size is known to avoid resizing.
Use stream().toList() (Java 16+) instead of Collectors.toList() for unmodifiable results.
🏛️ Architect's Note
In high-performance systems, avoid large in-memory lists of JPA entities. Instead of loading 10,000 Order objects into a List<Order>, use pagination (Pageable in Spring Data), streaming (Stream<Order> from JPA), or database aggregation. Loading large result sets into memory is a common cause of OOM errors in production.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
Core Java Interview Prep
Practice interview questions that connect directly to this technology track.
↗ Where this topic fits
Core Java Technology Guide
Return to the Core Java learning hub.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Sources
Sources / References
Use these Core Java references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide Core Java learning path
Browse the full Core Java topic collection and learning order on SplashRide.
Core Java Interview Prep
Practice Core Java interview questions and scenario-based answers.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Set
The Set interface — no duplicates, fast membership testing. HashSet, LinkedHashSet, TreeSet — when to use each.
Java Map Interface Explained: HashMap, LinkedHashMap, and TreeMap
Learn the Java Map interface with HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap, key-value lookup, ordering, performance, and real-world examples.