Deep Dive into Java ArrayList: Implementation, Core Methods, and Usage Patterns
This article provides a comprehensive overview of Java's ArrayList, covering its internal structure, key fields, constructors, core operations such as adding, removing, and searching elements, traversal techniques, fail‑fast behavior, and a comparison with Vector, all illustrated with original source code snippets.
The article begins with an introduction to the Java Collections Framework, highlighting topics such as multithreading, NIO, and concurrent containers, before focusing on the ArrayList implementation.
ArrayList Class Structure
ArrayList extends AbstractList and implements List, RandomAccess, Cloneable, and java.io.Serializable. Its most important internal members are Object[] elementData (the backing array) and int size (the number of stored elements).
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {Key static fields include serialVersionUID, DEFAULT_CAPACITY = 10, EMPTY_ELEMENTDATA, and DEFAULTCAPACITY_EMPTY_ELEMENTDATA, which are used to manage the initial and empty states of the backing array.
Constructors
ArrayList provides three constructors: a default constructor with an initial capacity of 10, a constructor that accepts a specific initial capacity, and a constructor that copies elements from an existing collection.
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); } } public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) { elementData = Arrays.copyOf(elementData, size, Object[].class); } } else { this.elementData = EMPTY_ELEMENTDATA; } }Capacity Management
The public ensureCapacity(int minCapacity) method allows users to manually increase the backing array size, while internal methods ensureCapacityInternal, ensureExplicitCapacity, and grow handle automatic expansion, typically increasing the capacity by 1.5×.
public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) ? 0 : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } }Core Operations
Adding elements:
public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; }Inserting at a specific index:
public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }Removing elements (by index, by object, range removal, bulk removal) is implemented with careful updates to modCount and null‑clearing of freed slots to aid garbage collection.
Setting an element:
public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; }Accessing elements:
public E get(int index) { rangeCheck(index); return elementData(index); }Search methods such as contains, indexOf, and lastIndexOf iterate over the backing array to locate the target.
Additional Public Methods
Methods like trimToSize(), size(), isEmpty(), clone(), toArray(), and generic toArray(T[] a) provide utility functions for size management, cloning, and array conversion.
Traversal Techniques
Four common ways to iterate over an ArrayList are demonstrated: using an Iterator, a ListIterator (which supports bidirectional traversal and element modification), index‑based random access (leveraging the RandomAccess interface), and the enhanced for‑each loop.
Fail‑Fast Behavior
ArrayList’s iterator is fail‑fast: it records a modCount and throws ConcurrentModificationException if the list is structurally modified during iteration.
Comparison with Vector
Vector implements the same List interface but synchronizes its mutating methods, making it thread‑safe at the cost of higher overhead. Sample synchronized add and insertElementAt methods are shown.
public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }The article concludes with references to several online resources and books such as "Effective Java" for further reading.
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.
Big Data Technology & Architecture
Wang Zhiwu, a big data expert, dedicated to sharing big data technology.
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.
