Card 04/ 08
All 8 cards
WalkthroughDifficulty: Intermediate1 min
What an ArrayList Does the Moment It Runs Out of Room
An array cannot grow, and an ArrayList is backed by an array and grows. Watching what happens at the boundary explains both its cost profile and a surprising number in its documentation.
From an empty list to one that has outgrown its array
Step 1 of 5
new ArrayList<>() allocates nothing
List<String> refs = new ArrayList<>();The backing array is a shared, empty one. Capacity is zero, and a list nobody ever adds to costs almost nothing, which matters when a program holds thousands of them.
The first add allocates ten slots
refs.add("A");Ten is the default initial capacity. Size is now one and capacity is ten, so the next nine adds cost nothing but a write.
The eleventh add finds the array full
There is no eleventh slot and no way to lengthen the array. The list allocates a new array about half as long again, which is fifteen slots.
Every element is copied across
Ten elements are copied from the old array into the new one, the list points at the new array, and the old one becomes garbage. Only then does the eleventh element go in.
Growth happens less and less often
| Growth | Capacity |
|---|---|
| Initial | 10 |
| First | 15 |
| Second | 22 |
| Third | 33 |
Because capacity grows by a proportion rather than by a fixed amount, the copies get further apart as the list gets longer. Averaged over many adds, appending is constant — which is why add is cheap despite occasionally copying everything.
The run to remember: growth is a copy, and its cost is spread thinly. When you know the final size, new ArrayList<>(50_000) skips every copy in the table above.