Pre-sizing ArrayList
#JAVATIP
Many developers don’t realize that most Java collections are backed by arrays and when you grow them dynamically, they silently perform resizing and copying, costing you performance and memory.
What Really Happens
ArrayList<String> arrayList = new ArrayList<>();
This creates ArrayList with the empty internal Object[] array.
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData;
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
Then when you add the first element , the empty ArrayList elementData will be expanded to DEFAULT_CAPACITY which is 10.
And each time the list exceeds capacity, the underlying array needs to be grow. Internally, JDK uses this line of code to determine the new size.
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
What’s happening here?
Let’s break down each part.
- ArraysSupport.newLength()
This is a low-level internal helper that calculates the ideal new array length. It balances:
- minimum required growth (to ensure the new element fits)
- preferred growth policy (to avoid frequent reallocations)
- Arrays.copyOf(…)
- After computing the new length, Java performs an array copy:
- Allocates a new, larger array
- Copies all old elements into it
This happens every time the capacity is exceeded and it’s not free.
Why Pre-sizing Helps
- Every time your ArrayList grows beyond capacity, this happens.
- It’s not cheap — array copying is O(n), and object allocation increases GC pressure.
- By pre-sizing the list (e.g., new ArrayList<>(expectedSize)), you can avoid multiple resizes and copy operations.
Caveat: Pre-sizing Isn’t Always Better
While pre-sizing improves performance when the size is known and reasonable, it has drawbacks if you overestimate:
List<String> list = new ArrayList<>(10_000_000);
- You just allocated a String[] array with 10 million slots.
- Even if you never use them, they consume real memory.
- That space sits idle in the heap, contributing to GC pressure.
- In extreme cases, it can even lead to OutOfMemoryError.
Java’s ArrayList gives you dynamic growth for free but that convenience hides copying costs. When you’re working with large batches, pre-sizing gives you better control over performance. Just don’t overdo it.
Pre-sizing ArrayList was originally published in Javarevisited on Medium, where people are continuing the conversation by highlighting and responding to this story.
This post first appeared on Read More