Java Collections
ArrayList
Complete lesson for ArrayList using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with Java OOP and Collections where relevant.
Basics — ArrayList
Section: Java Collections. ArrayList internals: grow policy, RandomAccess, complexity, and vs LinkedList.
A resizable array
ArrayListimplementsList,RandomAccess,Cloneable,Serializable. Backing store is anObject[].size()is the number of elements. **Capacity** is the array length. When full, it grows (typically 1.5× in OpenJDK).get(i)/set(i)are O(1).add(e)at the end is amortized O(1).add(i, e)/remove(i)are O(n) because elements shift.
import java.util.ArrayList;
import java.util.List;
public class ArrayListBasics {
public static void main(String[] args) {
List<String> cities = new ArrayList<>(4); // initial capacity
cities.add("Pune");
cities.add("Delhi");
cities.add(1, "Mumbai");
cities.remove("Delhi");
System.out.println(cities.get(0));
System.out.println(cities);
}
} ArrayList vs LinkedList
ArrayList | LinkedList | |
|---|---|---|
| Structure | Dynamic array | Doubly linked nodes |
get(i) | O(1) | O(n) |
add at end | Amortized O(1) | O(1) |
add/remove at front | O(n) | O(1) |
| Memory | Compact array | Per-node pointers + object header |
| Locality | Excellent (CPU cache) | Poor |
Implements Deque | No | Yes |
| Default choice for List | Yes | Rarely |
Common operations
ensureCapacity(n)avoids repeated growth if you know the size.trimToSize()shrinks the array tosize.remove(int)vsremove(Object): forArrayList,remove(1)removes **index** 1. Useremove(Integer.valueOf(1))to remove the value 1.
Advanced — ArrayList
Growth, fail-fast, and interview mistakes
- Growth copies the array (
Arrays.copyOf). Adding n elements from capacity 0 is still amortized O(n). - Iterators and for-each are fail-fast (
modCount). UseIterator.removeorremoveIf(Java 8). ArrayListis not synchronized.Vectoris the old synchronized list — preferCollections.synchronizedListor a concurrent structure.subListis a view: changes write through, and structural changes to the parent can invalidate the view.- Default initial capacity is 10 only after the first
addin modern OpenJDK (empty list starts with a shared empty array).
Tricky Interview Points
Q1) How does ArrayList grow?
Answer When size == capacity, it allocates a larger array (about 1.5×) and copies elements. add at the end is amortized O(1).
Q2) ArrayList vs LinkedList — which to pick?
Answer ArrayList almost always. Random access and cache locality win. Use LinkedList only if you truly need frequent end-to-end deque operations and already measured it — or just use ArrayDeque.
Q3) Why is get O(1)?
Answer Elements sit in a contiguous array. Index i is a single array load.
Q4) remove(1) on ArrayList<Integer>?
Answer Calls remove(int index), not remove(Object). Integer 1 as a value needs remove(Integer.valueOf(1)).
Q5) Is ArrayList synchronized?
Answer No. Concurrent add/get without external locking is unsafe.
Q6) What is RandomAccess?
Answer A marker interface telling algorithms that index access is cheap. ArrayList has it; LinkedList does not — binary search / some Collections methods choose different loops.
Simple Programs
Capacity and Integer remove trap
import java.util.ArrayList;
import java.util.List;
public class ArrayListTraps {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>();
nums.add(10);
nums.add(20);
nums.add(30);
nums.remove(Integer.valueOf(20)); // value, not index
System.out.println(nums); // [10, 30]
nums.remove(0); // index
System.out.println(nums); // [30]
}
} Problem Solving Tricks
- Pre-size with
new ArrayList<>(expected)when you know n. - Prefer
List.of(...)when the list never changes. - Use
removeIf(predicate)instead of a manual iterator loop. - Never store a
subListafter structurally changing the parent.
Practice Programs List
- Implement “remove all evens” three ways: index loop backward, Iterator,
removeIf. - Insert 100_000 elements, then
getthe middle — compare mentally to LinkedList. - Show
remove(1)vsremove(Integer.valueOf(1))onList. - Copy an array into an ArrayList with
new ArrayList<>(List.of(...))and then mutate the list. - Trigger CME and then fix it.