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.

Big Data Technology & Architecture
Big Data Technology & Architecture
Big Data Technology & Architecture
Deep Dive into Java ArrayList: Implementation, Core Methods, and Usage Patterns

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.

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.

JavaconcurrencyCollectionsData StructuresArrayList
Big Data Technology & Architecture
Written by

Big Data Technology & Architecture

Wang Zhiwu, a big data expert, dedicated to sharing big data technology.

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.