ArrayList is a resizable-array implementation of List that supports constant-time indexed reads.
Java ArrayList and indexed access
Start with the access pattern
If a UI needs the item at row 500 repeatedly, an indexed sequence fits. ArrayList reads that position directly. Inserting near the front shifts later references, so a workload with many such changes needs a separate analysis.
import java.util.ArrayList;
import java.util.List;
public class ReceiptBatch {
public static void main(String[] args) {
List<String> receiptIds = new ArrayList<>();
receiptIds.add("R-104");
receiptIds.add("R-105");
receiptIds.set(0, "R-104-corrected");
System.out.println(receiptIds.get(0));
}
}The output is R-104-corrected. Appending may resize the backing array; over many appends the cost is amortized O(1). A resize copies references and can produce a latency spike. The stored objects themselves are not duplicated.
Capacity and public views
Capacity is backing storage; size is the number of accessible elements. ensureCapacity does not add readable elements. get(size) is still invalid even when extra capacity has already been reserved.
subList is a view, not a detached ArrayList. Structural edits to the parent outside the view can invalidate assumptions made by the view. Copy the sublist when a reader needs independent structure, and include that O(k) copying cost.
Connected lessons
Continue with Java LinkedList: operations, internals and failure cases, Java LinkedList quiz.
Capacity and ownership are separate decisions
Capacity is storage reserved for references; size is the number of elements currently in the list. new ArrayList(100) does not create one hundred usable indexed elements. Calling get(0) before adding anything still fails. Use a measured capacity hint when a batch size is known, but do not reserve enormous buffers for every small request.
Growing the backing storage can copy existing references. Adding at the end is amortized constant work under ordinary growth, but one individual addition may perform a resize. Inserting or removing near the start shifts later references, so repeated front edits can produce quadratic work.
An ArrayList copy retains the same element references. If Receipt objects are mutable, a caller changing one receipt can affect both lists. The view and snapshot lesson distinguishes membership copies from independent object state.
Choose a mutation and traversal policy
Removing by index from a List of integers is not the same overload as removing an Integer value. Make the value type explicit when the business operation asks to remove a particular numeric ID.
Editing the list structurally during an ordinary enhanced-for traversal can invalidate its iterator. Use the iterator’s supported removal path, removeIf for a predicate, or a separate transformed result. Fail-fast behaviour detects mistakes on a best-effort basis; it is not a thread-safety guarantee.
Use ArrayDeque for a single-owner endpoint queue and a bounded blocking queue for producer/consumer admission. A collection choice should follow access patterns rather than its name.
Common Mistakes
Do not assume an unmodifiable List is an ArrayList. Removing while iterating needs an iterator or a deliberately chosen filter operation. A capacity setting is not an element count.
Compare the Python boundary
Python lists: slicing copies the outer sequence, not nested objects.
Next boundary checks
Continue with Java List.remove with Integer: index or value, Java LinkedList indexed loops: a hidden quadratic traversal.
