Deep Dive into Java ArrayList: How It Works Under the Hood
This article explores Java's ArrayList implementation in depth, covering its core interfaces, member variables, constructors, and the most commonly used methods, while illustrating how the internal array expands and how each operation manipulates the underlying data structure.
Overall Introduction
The Collection interface is the root of Java's collection hierarchy; it has no direct implementation, while Set and List extend it. A Set contains no duplicate elements and has no guaranteed order, whereas a List is ordered and may contain duplicates. Map is a separate interface that stores key‑value pairs, where keys must be unique but values may repeat.
Member Variables
ArrayList defines several key fields: DEFAULT_CAPACITY – the default initial capacity (10). EMPTY_ELEMENTDATA – a shared empty Object[] used when the list is created without a specified capacity. elementData – the internal Object[] that actually stores the elements. size – the number of elements currently stored in elementData, not the array length.
Constructors
ArrayList provides three constructors: ArrayList(int initialCapacity) – creates an internal array of the given size (or uses EMPTY_ELEMENTDATA if the size is zero). Negative values throw IllegalArgumentException. ArrayList() – uses DEFAULT_CAPACITY_EMPTY_ELEMENTDATA (effectively a capacity of 10). ArrayList(Collection<? extends E> c) – copies the elements of the supplied collection into a new internal array via c.toArray(), handling empty collections and type conversion as needed.
Common Methods
size()
Returns the current size field, i.e., the number of stored elements.
isEmpty()
Checks whether size == 0, indicating that the internal array holds no elements.
add(E e)
Appends an element to the end of the list. It first ensures sufficient capacity by calling ensureExplicitCapacity, which may trigger grow() if the array is full. After capacity is guaranteed, the element is stored at elementData[size++].
The capacity‑ensuring sequence involves:
Incrementing modCount (a modification counter from AbstractList).
Calculating the required minimum capacity and comparing it with elementData.length.
Calling grow() when needed.
add(int index, E element)
Inserts an element at the specified position, shifting subsequent elements one slot to the right using System.arraycopy. Bounds are checked, capacity is ensured, and modCount is updated.
clear()
Increments modCount, nulls out all entries in the internal array, and resets size to zero.
remove(int index)
Validates the index, increments modCount, retrieves the element to return, shifts following elements left with System.arraycopy, decrements size, and nulls the now‑vacant slot.
remove(Object o)
If o is null, the method scans for the first null entry and calls fastRemove (a streamlined version without bounds checking). Otherwise it searches for a matching element, removes it via the same shifting logic, and returns true if removal succeeded.
contains(Object o)
Delegates to indexOf(o) != -1. The indexOf method iterates over elementData, handling null specially, and returns the first matching index or -1 if not found.
get(int index)
Performs a bounds check and returns elementData[index].
set(int index, E element)
Similar to add(int, E) but overwrites the existing value at index without shifting other elements.
Conclusion
ArrayList is backed by a dynamically resized array; when the capacity is exceeded, it grows by roughly 1.5× in Java 8.
Array‑based storage gives fast random access but makes deletions and insertions costly due to element shifting and occasional array copying. Pre‑sizing the list when the expected size is known can avoid frequent reallocations.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
