AP Computer Science A • Data Collections

ArrayList Methods

Master the resizable list abstraction that powers dynamic data management in Java.

AP Computer Science A illustration with code, binary digits, and programming braces
Inside this lesson 9 sections 5 questions 5 figures

SECTION 1

Historical Context & Motivation

Fixed-size arrays have been a cornerstone of programming since the earliest high-level languages, but their rigid length requirement poses a fundamental design problem: developers must predict collection sizes at compile time. When Java was released in 1995, its creators recognized that real-world applications—inventory systems, student rosters, game entities—frequently need collections that grow and shrink at runtime. The Java Collections Framework (JCF), introduced in Java 2, addressed this gap by providing a unified architecture of interfaces and implementations for dynamic data structures. At the center of the framework sits ArrayList, a resizable-array implementation of the List interface that combines the random-access speed of an array with the flexibility of automatic resizing.

1995 • Java 1.0 Released

Sun Microsystems ships Java with built-in arrays but no standard resizable list class. Developers rely on the synchronized Vector class for dynamic storage.

1998 • Java Collections Framework (JCF)

Java 2 (JDK 1.2) introduces the Collections Framework, including ArrayList as a non-synchronized, high-performance alternative to Vector.

2004 • Generics Added (Java 5)

Type parameters such as ArrayList<String> eliminate risky casting and bring compile-time type safety to collections.

2014 • Java 8 Streams & Lambdas

Functional-style operations allow developers to filter, map, and reduce ArrayLists without explicit loops, broadening the API surface.

2020 • AP CSA Curriculum Emphasis

The College Board solidifies ArrayList as a tested topic in Unit 7 of the AP Computer Science A course, making its methods essential exam knowledge.

The core question ArrayList answers is deceptively simple: how do you maintain indexed, ordered access to elements while allowing the collection to change size on the fly? Understanding the methods that manipulate an ArrayList—adding, removing, accessing, and modifying elements—is essential for the AP exam and for writing robust Java programs in any professional context.

SECTION 2

Core Principles & Definitions

An ArrayList is a generic class in the java.util package that implements the List interface. It stores references to objects (not primitives) in a contiguous internal array and automatically resizes that backing array when capacity is exhausted. Because ArrayList uses zero-based indexing identical to standard arrays, transitioning between the two data structures is conceptually smooth. However, unlike arrays, ArrayList tracks its own size (the number of elements currently stored) independently of its internal capacity.

1

Dynamic Sizing

ArrayList grows automatically when elements are added beyond its current capacity, typically doubling the backing array. You never manage capacity manually on the AP exam.
2

Object References Only

ArrayList stores object references, so primitives like int must be wrapped as Integer via autoboxing.
3

Zero-Based Indexing

The first element occupies index 0 and the last element occupies index size() − 1. Out-of-bounds access throws IndexOutOfBoundsException.
4

Index Shifting

Inserting or removing an element in the middle shifts all subsequent elements right or left, respectively. This is a frequent source of off-by-one errors on the exam.
5

Generics & Type Safety

Declaring ArrayList<String> restricts the list to String objects, and the compiler enforces this constraint, preventing ClassCastException at runtime.

SECTION 3

Visual Explanation — ArrayList in Memory

ArrayList<String> — Internal StateIndex012345Value"A""B""C""D"nullnullsize = 4 · capacity = 6After list.add(2, "X") — insert at index 2Index012345Value"A""B""X""C""D"nullsize = 5 · capacity = 6shift rightAfter list.remove(1) — remove index 1Index012345Value"A""X""C""D"nullnullsize = 4 · capacity = 6
The diagram shows a six-slot backing array. After add(2, "X"), elements at indices 2–3 shift right. After remove(1), elements at indices 2–4 shift left and size decreases by one.

The diagram above captures the two most exam-critical operations: indexed insertion and indexed removal. When you call add(2, "X"), every element from index 2 onward shifts one position to the right before the new element is placed at index 2. When you call remove(1), the element at index 1 is returned and every element from index 2 onward shifts one position to the left, closing the gap. Both operations mutate the size() accordingly, and the internal capacity remains unchanged unless a resize is triggered.

SECTION 4

How ArrayList Methods Work

AP-Tested ArrayList Methods

Method SignatureReturn TypeBehavior
add(E obj)booleanAppends obj to the end; always returns true.
add(int index, E obj)voidInserts obj at index; shifts subsequent elements right.
get(int index)EReturns the element at index without modifying the list.
set(int index, E obj)EReplaces the element at index with obj; returns the old element.
remove(int index)ERemoves and returns the element at index; shifts subsequent elements left.
size()intReturns the number of elements currently in the list (not the capacity).

The six ArrayList methods tested on the AP CSA exam

ℹ
Common Trap: remove() with Integer Lists

Notice that add(E obj) returns boolean while add(int index, E obj) returns void. Similarly, set and remove both return the displaced element, which is useful when you need to capture or inspect the value being replaced or deleted. The get method is a pure accessor—it never mutates the list. On the AP exam, questions frequently test whether students know which methods modify the list and which do not.

SECTION 5

Traversal & Modification Patterns

Traversing an ArrayList while simultaneously modifying it is one of the trickiest topics on the AP CSA exam. There are two primary traversal mechanisms: the standard indexed for loop and the enhanced for loop (for-each). The indexed loop grants full control over the index variable, making it safe to add or remove elements when you manage the index correctly. The enhanced for loop, by contrast, does not expose an index and will throw a ConcurrentModificationException if you modify the list during iteration.

Removing During Traversal — Index ManagementGoal: Remove all occurrences of "B" from ["A", "B", "B", "C"]Pass 1: i = 0"A""B""B""C"i=0 ↑"A" ≠ "B" → i++Pass 2: i = 1 — match found!"A""B""B""C"i=1 ↑ remove!remove(1); do NOT i++After remove — elements shift left"A""B""C"i=1 still ↑"B" shifted into i=1 → check againPass 3: i = 1 again — second "B" caught"A""C"i=1 ↑ not "B" → i++Final list: ["A", "C"] ✓
When removing during a forward traversal, do not increment i on a removal pass; the left-shift brings the next element to the current index. Alternatively, traverse backwards from size() − 1 to 0, which avoids this issue entirely.
ℹ
Backward Traversal Alternative

SECTION 6

Worked Example — Building and Querying a Roster

Consider the following scenario: a teacher maintains a student roster as an ArrayList<String>. The code below builds the roster, performs several mutations, and prints the final state. Trace each operation carefully.

Worked example

  1. 1

    Step 1 — Initialize and Populate

    Create the list and add four names: ArrayList<String> roster = new ArrayList<String>(); roster.add("Alice"); roster.add("Bob"); roster.add("Carol"); roster.add("Dave");
    roster → ["Alice", "Bob", "Carol", "Dave"], size = 4
  2. 2

    Step 2 — Indexed Insertion

    roster.add(1, "Eve"); Inserts "Eve" at index 1. "Bob", "Carol", and "Dave" each shift one position to the right.
    roster → ["Alice", "Eve", "Bob", "Carol", "Dave"], size = 5
  3. 3

    Step 3 — Set (Replace)

    String old = roster.set(3, "Carlos"); Replaces the element at index 3 ("Carol") with "Carlos". The method returns the old value "Carol", stored in old.
    roster → ["Alice", "Eve", "Bob", "Carlos", "Dave"], old = "Carol"
  4. 4

    Step 4 — Remove by Index

    roster.remove(0); Removes and returns "Alice". All remaining elements shift left.
    roster → ["Eve", "Bob", "Carlos", "Dave"], size = 4
  5. 5

    Step 5 — Access and Size Check

    System.out.println(roster.get(2) + " " + roster.size()); roster.get(2) returns "Carlos" (index 2 after the previous removal). roster.size() returns 4.
    Output: Carlos 4

SECTION 7

ArrayList vs. Array — Strengths & Limitations

FeatureArrayArrayList
SizeFixed at creation (.length)Dynamic (.size())
PrimitivesSupports int, double, etc. directlyRequires wrapper classes (Integer, Double)
Access syntaxarr[i]list.get(i)
Mutation syntaxarr[i] = vallist.set(i, val)
Insert / removeManual shifting requiredBuilt-in methods with automatic shifting
Performance (random access)O(1)O(1)
Performance (insert/remove middle)O(n) — manualO(n) — automatic

Key differences between arrays and ArrayLists in Java

★

Key takeaway

WHEN TO USE WHICH

SECTION 8

Connection to Advanced Data Structures

ArrayList (AP CSA)Advanced Alternatives
Backed by a resizable array; O(n) insert/remove in the middle.LinkedList — O(1) insert/remove at known position, but O(n) random access.
Not thread-safe; for single-threaded use.CopyOnWriteArrayList — thread-safe variant that clones the backing array on each write.
Stores only objects; autoboxing adds overhead.IntStream / primitive arrays — avoid boxing entirely for numeric workloads.
Ordered by insertion; no duplicate control.HashSet / TreeSet — enforce uniqueness; TreeSet also maintains sorted order.

ArrayList in the broader Collections landscape

In a college-level data structures course, you will formalize the performance characteristics of ArrayList in terms of amortized analysis. Although a single add that triggers a resize copies all n elements (O(n)), the doubling strategy ensures that the average cost per insertion is O(1) amortized. Understanding this tradeoff is foundational for algorithm design, and the intuition you build tracing ArrayList operations on the AP exam transfers directly to these more advanced analyses.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Which of the following ArrayList method calls does NOT modify the list? A) list.add("X") B) list.set(0, "Y") C) list.get(2) D) list.remove(1)
  • A. list.add("X")
  • B. list.set(0, "Y")
  • C. list.get(2)
  • D. list.remove(1)
Show answer (C)
C is correct. The get(int index) method is a pure accessor that returns the element at the given index without altering the list's contents or size. A is wrong because add appends an element, increasing the size. B is wrong because set replaces an existing element, mutating the list's contents. D is wrong because remove deletes an element and shifts subsequent elements left.

Question 2: BASIC CALCULATION

Consider the following code: ArrayList<String> items = new ArrayList<String>(); items.add("P"); items.add("Q"); items.add("R"); items.add(1, "S"); items.set(3, "T"); items.remove(0); What does items contain after execution? A) ["S", "Q", "T"] B) ["Q", "S", "T"] C) ["S", "Q", "R"] D) ["P", "S", "T"]
  • A. ["S", "Q", "T"]
  • B. ["Q", "S", "T"]
  • C. ["S", "Q", "R"]
  • D. ["P", "S", "T"]
Show answer (A)
A is correct. Trace: after three adds → ["P", "Q", "R"]. add(1, "S") → ["P", "S", "Q", "R"]. set(3, "T") replaces index 3 → ["P", "S", "Q", "T"]. remove(0) removes "P" → ["S", "Q", "T"]. B is wrong because it reverses the order of S and Q. C is wrong because it ignores the set operation. D is wrong because it ignores the remove operation.

Question 3: INTERMEDIATE

What is the output of the following code? ArrayList<Integer> nums = new ArrayList<Integer>(); nums.add(5); nums.add(10); nums.add(15); nums.add(20); for (int i = nums.size() - 1; i >= 0; i--) { if (nums.get(i) % 10 == 0) { nums.remove(i); } } System.out.println(nums); A) [5, 15] B) [5, 10, 15] C) [5, 15, 20] D) [5]
  • A. [5, 15]
  • B. [5, 10, 15]
  • C. [5, 15, 20]
  • D. [5]
Show answer (A)
A is correct. The backward loop starts at i=3: 20 % 10 == 0, so remove index 3 → [5, 10, 15]. Then i=2: 15 % 10 == 5, skip. i=1: 10 % 10 == 0, remove index 1 → [5, 15]. i=0: 5 % 10 == 5, skip. Final: [5, 15]. B is wrong because it fails to remove 10. C is wrong because it fails to remove 20. D is wrong because it removes 15, which is not divisible by 10.

Question 4: APPLIED

Write a method removeDuplicates that takes an ArrayList<String> and removes all duplicate values so that only the first occurrence of each string remains. The order of remaining elements must be preserved. Do not use any data structures other than ArrayList. Method signature: public static void removeDuplicates(ArrayList<String> list)
Show answer
Sample Solution: public static void removeDuplicates(ArrayList<String> list) { for (int i = 0; i < list.size(); i++) { for (int j = i + 1; j < list.size(); j++) { if (list.get(i).equals(list.get(j))) { list.remove(j); j--; // adjust index after removal } } } } Rubric Breakdown: • Point 1: Outer for loop from 0 to size() iterates through each element. • Point 2: Inner for loop from i+1 to size() compares the current element with all elements that follow. • Point 3: Calls list.remove(j) when a match is found, correctly removing the later duplicate. • Point 4: Decrements j after removal (j--) so the element that shifted into position j is checked on the next iteration. • Point 5: Because the outer loop advances normally and duplicates are always removed from later positions, the first occurrence is preserved and order is maintained.

Question 5: CRITICAL THINKING

A student writes the following code to remove all negative numbers from an ArrayList<Integer>: for (int i = 0; i < nums.size(); i++) { if (nums.get(i) < 0) { nums.remove(i); } } (a) Explain the specific bug in this code by giving an input that produces incorrect output. (b) Provide two distinct fixes and explain why each works.
Show answer
(a) Bug Explanation: When nums = [-1, -2, 3], at i=0 the code removes -1, making the list [-2, 3]. The loop then increments i to 1 and checks index 1 (which is 3), completely skipping -2 that shifted into index 0. The result is [-2, 3] instead of the expected [3]. (b) Two Fixes: • Fix 1 — Decrement after removal: Add i--; inside the if block after remove. This counteracts the loop's i++, keeping i at the same position so the element that shifted in is examined. • Fix 2 — Backward traversal: Change the loop to for (int i = nums.size() - 1; i >= 0; i--). Removing an element only shifts elements at indices greater than i, all of which have already been processed, so no element is skipped.

Varsity Tutors • AP Computer Science A • ArrayList Methods