<code>ArrayList</code> in Java β€” The Default Growable List

ArrayList is Java's go-to list. It's backed by a growable array, gives O(1) random access, and is faster than any other List implementation for almost every real workload.

Basics

var list = new ArrayList<String>();
list.add("alpha");
list.add("beta");
list.add(0, "zero");             // insert at index 0

String first = list.get(0);       // O(1)
list.set(1, "ALPHA");             // replace
list.remove("beta");              // by value β€” O(n)
list.remove(0);                   // by index β€” O(n) for shift
list.size();                      // current count

for (String s : list) { ... }
list.forEach(System.out::println);

Capacity vs size

An ArrayList tracks two numbers: the size (how many elements are stored) and the capacity (how big the backing array is). When size == capacity and you add one more, the array is copied into a new one ~1.5Γ— larger. That's where "amortised" O(1) comes from β€” occasional resize, most adds cheap.

// Pre-size when you know the expected count
var list = new ArrayList<String>(10_000);

// Reclaim unused capacity
list.trimToSize();

From an existing collection

var copy = new ArrayList<>(other);         // defensive copy
var fromStream = stream.collect(Collectors.toCollection(ArrayList::new));
var viaList = new ArrayList<>(List.of(1, 2, 3));

Iteration and modification

// ❌ ConcurrentModificationException
for (String s : list) if (s.isEmpty()) list.remove(s);

// βœ… Iterator.remove
var it = list.iterator();
while (it.hasNext()) if (it.next().isEmpty()) it.remove();

// βœ… removeIf β€” Java 8+, cleanest
list.removeIf(String::isEmpty);

ArrayList vs alternatives

NeedPick
Default listArrayList
Frequent add/remove at both endsArrayDeque
Immutable, small, known at build timeList.of(...)
Immutable copy of an existing listList.copyOf(other)
Thread-safeCopyOnWriteArrayList (read-heavy) or a mutable list + explicit lock

Common mistakes

  • Using LinkedList instead β€” almost always slower than ArrayList due to cache misses.
  • Not pre-sizing large lists β€” each resize copies everything. new ArrayList<>(n) if you know the count.
  • Returning the internal list β€” callers can corrupt your state. Return List.copyOf(internal).
  • Treating List.of(...) as mutable β€” it isn't; add throws. Wrap in new ArrayList<>(List.of(...)) if you need to mutate.

Related

Pillar: Java collections. Siblings: LinkedList, ArrayDeque, Iterator.