Arrays and ArrayLists appear on every AP CS A exam, every year. At least one of the four free-response questions is dedicated to array or ArrayList manipulation, and array traversal shows up constantly in the multiple-choice section. If you want to score well on AP CS A, this is the topic you cannot afford to be shaky on.
This guide covers everything the exam tests: how arrays and ArrayLists work, how to traverse and manipulate them, the algorithms you need to know cold, the mistakes that cost students points, and the FRQ patterns that repeat year after year.
Part 1: Arrays
What an array is
An array is a fixed-size, ordered collection of elements of the same type. "Fixed-size" is the key phrase: once you create an array, its length cannot change. If you declare an array of 10 integers, it will always hold exactly 10 integers.
Arrays in Java are zero-indexed: the first element is at index 0, the last element is at index length - 1. This is different from everyday counting, and off-by-one errors from forgetting this are among the most common mistakes on the exam.
Declaring and initializing arrays
There are two ways to create an array in Java.
Option 1: declare with a size. This creates the array and fills it with default values (0 for int, 0.0 for double, false for boolean, null for objects).
int[] scores = new int[5]; // [0, 0, 0, 0, 0]
double[] prices = new double[3]; // [0.0, 0.0, 0.0]
String[] names = new String[4]; // [null, null, null, null]
Option 2: initialize with values. The size is inferred from the number of values provided.
int[] scores = {92, 85, 78, 91, 88};
String[] days = {"Mon", "Tue", "Wed", "Thu", "Fri"};
Accessing and modifying elements
Use bracket notation with an index to read or write a specific element.
int[] scores = {92, 85, 78, 91, 88};
System.out.println(scores[0]); // 92 (first element)
System.out.println(scores[4]); // 88 (last element)
scores[2] = 95; // changes 78 to 95
// scores is now {92, 85, 95, 91, 88}
Accessing an index that doesn't exist throws an ArrayIndexOutOfBoundsException at runtime. Accessing scores[5] on a 5-element array (valid indices 0–4) is one of the most common runtime errors on the exam.
The length property
array.length gives the number of elements. Note: it's a property, not a method, so there are no parentheses.
int[] scores = {92, 85, 78, 91, 88};
System.out.println(scores.length); // 5
System.out.println(scores[scores.length - 1]); // 88 (last element)
Using scores.length instead of a hardcoded number is important: it keeps your code correct even if the array size changes.
Traversing arrays with a for loop
The standard traversal pattern iterates from index 0 to length - 1.
int[] scores = {92, 85, 78, 91, 88};
for (int i = 0; i < scores.length; i++) {
System.out.println(scores[i]);
}
This gives you both the index (i) and the value (scores[i]). Use a standard for loop whenever you need the index, for example to compare adjacent elements, modify elements in place, or traverse in reverse.
Traversing with an enhanced for loop
The enhanced for loop (also called a "for-each" loop) iterates through values directly, without an index variable.
int[] scores = {92, 85, 78, 91, 88};
for (int score : scores) {
System.out.println(score);
}
This is cleaner when you only need the value, but it has two important limitations:
- You cannot modify the array through the loop variable. Assigning to
scoreinside the loop does not change the array. - You don't have access to the index. If you need to know where in the array you are, use a standard
forloop.
Essential array algorithms
These are the patterns that appear most often on the exam, both in MCQ and FRQ. Know each one well enough to write it from memory.
Sum and average:
public static double average(int[] arr) {
int sum = 0;
for (int val : arr) {
sum += val;
}
return (double) sum / arr.length;
}
The cast to double before dividing is critical. Without it, you get integer division and lose the decimal portion.
Find the minimum (or maximum):
public static int findMin(int[] arr) {
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
return min;
}
Start min at arr[0], not at 0 or Integer.MAX_VALUE, unless the problem specifically requires it. Starting at arr[0] is simpler and avoids edge cases. Begin the loop at index 1 since you've already accounted for index 0.
Linear search:
public static int indexOf(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
return i;
}
}
return -1; // target not found
}
Returning -1 when the target isn't found is the standard convention. The exam expects this pattern.
Count elements matching a condition:
public static int countEvens(int[] arr) {
int count = 0;
for (int val : arr) {
if (val % 2 == 0) {
count++;
}
}
return count;
}
Reverse traversal:
for (int i = arr.length - 1; i >= 0; i--) {
System.out.println(arr[i]);
}
Start at arr.length - 1 (the last index) and decrement until i >= 0. The condition is >= 0, not > 0, because index 0 is a valid element.
Shifting elements left (to remove an element):
// Remove the element at index k by shifting everything after it left
for (int i = k; i < arr.length - 1; i++) {
arr[i] = arr[i + 1];
}
After this loop, the last element is duplicated (both arr[arr.length - 2] and arr[arr.length - 1] hold the same value). Arrays can't shrink, so you'd typically track a logical size separately or switch to an ArrayList.
Part 2: ArrayLists
What an ArrayList is
An ArrayList is a resizable list that can grow and shrink dynamically. Unlike an array, you don't have to know the size in advance. Elements can be added or removed at any time, and the ArrayList adjusts its size automatically.
ArrayLists can only hold objects, not primitives. To store integers, use Integer (the wrapper class); Java automatically converts between int and Integer through autoboxing and unboxing.
Importing and declaring an ArrayList
import java.util.ArrayList;
ArrayList<Integer> scores = new ArrayList<Integer>();
ArrayList<String> names = new ArrayList<String>();
The type goes inside angle brackets. On the AP exam, you're expected to include the import statement when writing code that uses ArrayList.
Essential ArrayList methods
| Method | What It Does | Example |
|---|---|---|
add(value) | Appends value to the end | list.add(42) |
add(index, value) | Inserts value at index, shifting elements right | list.add(2, 99) |
get(index) | Returns the element at index | list.get(0) |
set(index, value) | Replaces the element at index with value, returns old value | list.set(1, 77) |
remove(index) | Removes and returns the element at index, shifting elements left | list.remove(3) |
size() | Returns the number of elements | list.size() |
Note that ArrayList uses size(), not length. Mixing these up is a very common exam mistake.
Traversing an ArrayList
Both loop styles work. Use a standard for loop when you need the index; use an enhanced for loop when you only need the value.
ArrayList<Integer> scores = new ArrayList<Integer>();
scores.add(92);
scores.add(85);
scores.add(78);
// Standard for loop
for (int i = 0; i < scores.size(); i++) {
System.out.println(scores.get(i));
}
// Enhanced for loop
for (int score : scores) {
System.out.println(score);
}
Removing elements during traversal
This is one of the most tested ArrayList patterns on the exam. Removing an element during a forward traversal shifts all subsequent elements left by one, causing the loop to skip the element that moved into the removed element's position.
The wrong way (skips elements):
// BUG: skips elements after each removal
for (int i = 0; i < list.size(); i++) {
if (list.get(i) < 0) {
list.remove(i); // element at i+1 shifts to i, then i++ skips it
}
}
Fix 1: iterate from back to front. Removing from the end doesn't affect earlier indices.
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i) < 0) {
list.remove(i);
}
}
Fix 2: decrement the index after removal.
for (int i = 0; i < list.size(); i++) {
if (list.get(i) < 0) {
list.remove(i);
i--; // re-check the same index after the shift
}
}
Either fix works. The backwards traversal (Fix 1) is generally cleaner and less error-prone.
Part 3: Arrays vs. ArrayLists
| Array | ArrayList | |
|---|---|---|
| Size | Fixed at creation | Dynamic, grows and shrinks |
| Element types | Primitives or objects | Objects only (use wrapper classes) |
| Access syntax | arr[i] | list.get(i) |
| Length/size | arr.length (property) | list.size() (method) |
| Add elements | Not possible after creation | list.add(value) |
| Remove elements | Manual shifting required | list.remove(index) |
| When to use | Size is known and fixed | Size varies or elements are added/removed |
On FRQs, the question will tell you whether to use an array or an ArrayList. Read the method signature carefully: if the parameter is int[], use array syntax; if it's ArrayList<Integer>, use ArrayList methods.
Part 4: 2D Arrays
A 2D array is an array of arrays. Think of it as a table with rows and columns.
Declaration and initialization
int[][] grid = new int[3][4]; // 3 rows, 4 columns, all zeros
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Dimensions
matrix.lengthis the number of rows (3 in the example above).matrix[0].lengthis the number of columns (3 in the example above).
Mixing up rows and columns is one of the most common 2D array errors on the exam.
Row-major traversal (left to right, top to bottom)
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[row].length; col++) {
System.out.print(matrix[row][col] + " ");
}
System.out.println();
}
Column-major traversal (top to bottom, left to right)
for (int col = 0; col < matrix[0].length; col++) {
for (int row = 0; row < matrix.length; row++) {
System.out.print(matrix[row][col] + " ");
}
System.out.println();
}
Swap the loop order to change the traversal direction. The inner loop variable changes fastest; the outer loop variable changes slowest.
Common 2D array algorithms
Sum of all elements:
int total = 0;
for (int[] row : matrix) {
for (int val : row) {
total += val;
}
}
Find the largest value:
int max = matrix[0][0];
for (int[] row : matrix) {
for (int val : row) {
if (val > max) {
max = val;
}
}
}
Row sums (sum each row independently):
for (int row = 0; row < matrix.length; row++) {
int rowSum = 0;
for (int col = 0; col < matrix[row].length; col++) {
rowSum += matrix[row][col];
}
System.out.println("Row " + row + " sum: " + rowSum);
}
Part 5: Common Exam Mistakes
These are the specific errors that cost students points most often on the array and ArrayList portions of the exam.
-
Using
arr.length()instead ofarr.length. Arrays use a property, not a method.arr.length()is a compile error.arr.lengthis correct. (Strings use.length()with parentheses, which makes this confusion understandable but still wrong.) -
Using
list.lengthinstead oflist.size(). ArrayLists use a method.list.lengthdoesn't exist.list.size()is correct. -
Off-by-one in the loop bound.
for (int i = 0; i <= arr.length; i++)will throwArrayIndexOutOfBoundsExceptionon the last iteration because indexarr.lengthdoesn't exist. The correct bound isi < arr.length. -
Modifying array elements through an enhanced for loop variable.
for (int val : arr) { val = 0; }does not change the array.valis a copy of the element. To modify elements in place, use a standardforloop witharr[i] = 0. -
Skipping elements when removing from an ArrayList during a forward traversal.
After
list.remove(i), the element at indexi+1shifts to indexi. If you then incrementi, you skip it. Iterate backwards or decrementiafter each removal. -
Swapping rows and columns in a 2D array.
matrix[row][col], notmatrix[col][row]. The first index is always the row. -
Using
arr.lengthinstead ofarr[0].lengthfor the number of columns in a 2D array.matrix.lengthis the number of rows.matrix[0].lengthis the number of columns in the first row. -
Forgetting to initialize a result variable before a loop.
Declaring
int sum;and then usingsuminside a loop without assigning it a value first is a compile error in Java. Always initialize:int sum = 0;.
Part 6: FRQ Patterns to Know
The College Board uses a small set of recurring FRQ patterns for arrays and ArrayLists. Recognizing the pattern quickly lets you start writing code immediately instead of spending time figuring out the approach.
| Pattern | What It Asks | Key Technique |
|---|---|---|
| Filter and collect | Return a new array or ArrayList containing only elements that meet a condition | Build a new ArrayList during traversal; convert to array if required |
| In-place removal | Remove all elements from an ArrayList that meet a condition | Traverse backwards; call remove(i) |
| Search and return index | Find the first (or last) element matching a condition; return its index or -1 | Linear search with early return; return -1 after the loop |
| Accumulate and compute | Calculate a sum, count, average, or running total across an array | Initialize accumulator before loop; return after loop |
| Find min/max with index | Return the index of the minimum or maximum element, not the value itself | Track both the best value and the index where it was found |
| 2D row/column operation | Process all elements in a specific row or column; compute row sums, column averages | Fix one loop variable, iterate the other; pick traversal order carefully |
| Shift and insert | Insert a value into a specific position by shifting elements | Shift right-to-left before inserting; shift left-to-right for removal |
The filter-and-collect pattern in detail
This pattern comes up frequently enough to deserve its own example. The task: given an array of integers, return a new array containing only the positive values.
public static int[] positiveValues(int[] arr) {
// First pass: count how many positives there are
int count = 0;
for (int val : arr) {
if (val > 0) {
count++;
}
}
// Allocate result array of exactly the right size
int[] result = new int[count];
// Second pass: fill result
int index = 0;
for (int val : arr) {
if (val > 0) {
result[index] = val;
index++;
}
}
return result;
}
When the return type is an ArrayList instead of an array, the approach is simpler: just add() matching elements to a new ArrayList during a single pass.
public static ArrayList<Integer> positiveValues(int[] arr) {
ArrayList<Integer> result = new ArrayList<Integer>();
for (int val : arr) {
if (val > 0) {
result.add(val);
}
}
return result;
}
Quick Reference: Array vs. ArrayList Syntax
| Operation | Array | ArrayList |
|---|---|---|
| Declare | int[] arr = new int[n]; | ArrayList<Integer> list = new ArrayList<Integer>(); |
| Get length/size | arr.length | list.size() |
| Read element | arr[i] | list.get(i) |
| Write element | arr[i] = val; | list.set(i, val); |
| Add to end | Not possible | list.add(val); |
| Remove by index | Manual shift required | list.remove(i); |
| Standard for loop | for (int i = 0; i < arr.length; i++) | for (int i = 0; i < list.size(); i++) |
| Enhanced for loop | for (int val : arr) | for (int val : list) |
Ready to Practice with an Expert?
Arrays and ArrayLists are skills that improve fastest with feedback on real code, not just reading examples. ExamReadyUSA's 4-week AP CS A Crash Course includes dedicated sessions on arrays, ArrayLists, and 2D arrays, with graded FRQ practice and line-by-line feedback from Namrata Poladia, a College Board AP Reader. Groups are capped at 5 students so every question gets answered.