Fundamentals 9 min read

Why Does Java’s ArrayList Default to a Capacity of 10?

This article explains why Java’s ArrayList uses a default initial capacity of 10, contrasts it with HashMap’s 16‑element default, and walks through the lazy‑initialization logic and growth algorithm that keep the capacity at ten until the first element is added.

Senior Brother's Insights
Senior Brother's Insights
Senior Brother's Insights
Why Does Java’s ArrayList Default to a Capacity of 10?

Background

When inspecting the source code of ArrayList, the default initial capacity appears to be 10, which raises the question of why it differs from the HashMap default of 16.

Why HashMap’s Initial Capacity Is 16

In Java 8, HashMap defines two key constants:

/**
 * The default initial capacity - MUST be a power of two.
 */
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

/**
 * The load factor used when none specified in constructor.
 */
static final float DEFAULT_LOAD_FACTOR = 0.75f;

The array backing a HashMap starts with 16 slots; when the number of entries reaches 75 % of this size, the map expands to twice its capacity. Using a power‑of‑two size allows the hash computation to use bit‑wise operations, reducing collisions and improving lookup speed.

ArrayList’s Default Capacity Is 10

The source of ArrayList in Java 8 defines:

/** Default initial capacity. */
private static final int DEFAULT_CAPACITY = 10;

From JDK 1.2 through JDK 1.6 the value was always 10. Starting with JDK 1.7, the class employs lazy initialization: the internal array is initially an empty shared array.

/**
 * Shared empty array instance used for default sized empty instances. We
 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
 * first element is added.
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/** Constructs an empty list with an initial capacity of ten. */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

How the Capacity Is Determined on First Add

The add method triggers capacity calculation:

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

It calls ensureCapacityInternal, which delegates to calculateCapacity:

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

If the internal array is still the shared empty array, the method returns the larger of DEFAULT_CAPACITY (10) and the requested minCapacity. Thus the first insertion forces the capacity to become 10.

Subsequent growth is handled by grow:

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5× old size
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

The growth factor is 1.5×, matching the classic ArrayList expansion strategy.

Why the Number 10?

There is no formal specification explaining the choice of 10; it appears to be a pragmatic balance between memory usage and the need for occasional resizing. Ten is small enough to avoid wasting space for short‑lived lists, yet large enough to reduce the frequency of the first resize. The decision likely reflects empirical performance testing rather than a theoretical requirement.

Other collection classes use similar “reasonable” defaults: Vector also defaults to 10, HashSet and HashMap to 16, and Hashtable to 11, each chosen for historical or performance reasons.

Conclusion

Java’s ArrayList always starts with a logical capacity of 10, but the actual array allocation is deferred until the first element is added, saving memory for many empty lists. The choice of 10 is a practical compromise rather than a mathematically derived value.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaHashMapData StructuresArrayListlazy-initializationDefault Capacity
Senior Brother's Insights
Written by

Senior Brother's Insights

A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.