AP CSA Unit 4: Data Collections - Ultimate Study Guide 2025-2026

AP Computer Science A

Unit 4: Data Collections

Ultimate Study Guide - 2025-2026 Curriculum

30-40% of AP Exam | FRQ Questions 3 & 4

Unit 4 Overview

Unit 4: Data Collections is the largest and most important unit on the AP CSA Exam. It covers everything from basic arrays to complex algorithms, and accounts for nearly 40% of your exam score. Master this unit, and you're well on your way to a 4 or 5.

Exam Weight: 30-40% of Multiple Choice

Plus TWO of the four Free Response Questions:

  • FRQ #3: Data Analysis with ArrayList - traverse, filter, and process ArrayList data
  • FRQ #4: 2D Array - nested loops, row/column processing, grid manipulation

This means Unit 4 content appears in roughly 50% of your total exam score!

What's New for 2025-2026

†• NEW Topic: File I/O with Scanner

The College Board added reading from text files using the File and Scanner classes. This is practical, real-world programming that connects to data analysis. You'll need to know:

  • hasNext(), nextLine(), nextInt(), next()
  • The throws IOException clause
  • Processing file data into arrays or ArrayLists

Unit 4 Topic Breakdown

Topic Content Exam Focus
4.1 Ethical & Social Issues Around Data Collection Conceptual MCQ
4.2 Introduction to Using Data Sets Conceptual MCQ
4.3 Array Creation and Access MCQ, FRQ 3 & 4
4.4 Array Traversals MCQ, FRQ 3 & 4
4.5 Implementing Array Algorithms MCQ, FRQ 3 & 4
4.6 Using Text Files NEW MCQ, possibly FRQ
4.7 Wrapper Classes (Integer, Double) MCQ, FRQ 3
4.8 ArrayList Methods Heavy MCQ, FRQ 3
4.9 ArrayList Traversals Heavy MCQ, FRQ 3
4.10 Implementing ArrayList Algorithms Heavy MCQ, FRQ 3
4.11 2D Array Creation and Access Heavy MCQ, FRQ 4
4.12 2D Array Traversals Heavy MCQ, FRQ 4
4.13 Implementing 2D Array Algorithms Heavy MCQ, FRQ 4
4.14 Searching Algorithms MCQ (tracing)
4.15 Sorting Algorithms MCQ (tracing)
4.16 Recursion MCQ (tracing)
4.17 Recursive Searching and Sorting MCQ (tracing)

Skills You'll Master

  • Create, access, and modify arrays, ArrayLists, and 2D arrays
  • Write traversal loops (standard for, enhanced for, backward)
  • Implement standard algorithms: sum, average, min/max, count, search, filter
  • Read data from text files
  • Trace searching algorithms (linear and binary search)
  • Trace sorting algorithms (selection and insertion sort)
  • Understand and trace recursive methods
  • Avoid common pitfalls that lose points on FRQs

Arrays

An array is a container that holds a fixed number of values of a single type. Once created, an array's size cannot change. Arrays are the foundation of data collections in Java.

Creating Arrays

Method 1: Declare Size (Elements Get Default Values)

// Create array of 5 integers - all initialized to 0
int[] numbers = new int[5];
// numbers = [0, 0, 0, 0, 0]

// Create array of 3 Strings - all initialized to null
String[] names = new String[3];
// names = [null, null, null]

// Create array of 4 doubles - all initialized to 0.0
double[] prices = new double[4];
// prices = [0.0, 0.0, 0.0, 0.0]

// Create array of 2 booleans - all initialized to false
boolean[] flags = new boolean[2];
// flags = [false, false]

Method 2: Initialize with Values (Size is Inferred)

// Initialize with specific values
int[] scores = {85, 90, 78, 92, 88};
// scores.length = 5

String[] colors = {"red", "green", "blue"};
// colors.length = 3

double[] temps = {98.6, 99.1, 97.8};
// temps.length = 3

Default Values by Type

Element Type Default Value Example
int 0 new int[3] → [0, 0, 0]
double 0.0 new double[2] → [0.0, 0.0]
boolean false new boolean[2] → [false, false]
String (and all objects) null new String[2] → [null, null]

Accessing and Modifying Elements

int[] arr = {10, 20, 30, 40, 50};

// Access elements using index (0-based!)
System.out.println(arr[0]);  // 10 (first element)
System.out.println(arr[2]);  // 30 (third element)
System.out.println(arr[4]);  // 50 (last element)

// Get array length (NOT a method - no parentheses!)
System.out.println(arr.length);  // 5

// Access last element (common pattern)
System.out.println(arr[arr.length - 1]);  // 50

// Modify elements
arr[0] = 100;   // arr = [100, 20, 30, 40, 50]
arr[2] = 300;   // arr = [100, 20, 300, 40, 50]
arr[4] = arr[3] + 10;  // arr = [100, 20, 300, 40, 50]

Array Index Diagram

// Visual representation of array indexing:
//
//   Index:    0     1     2     3     4
//          +-----+-----+-----+-----+-----+
//   arr:   | 10  | 20  | 30  | 40  | 50  |
//          +-----+-----+-----+-----+-----+
//
//   arr.length = 5
//   Valid indices: 0, 1, 2, 3, 4
//   First element: arr[0]
//   Last element: arr[arr.length - 1] = arr[4]
ArrayIndexOutOfBoundsException

Accessing an index less than 0 or greater than or equal to length causes a runtime crash:

int[] arr = {10, 20, 30};  // length = 3, valid indices: 0, 1, 2

arr[3]   // CRASH! Index 3 doesn't exist
arr[-1]  // CRASH! Negative indices don't exist
arr[arr.length]  // CRASH! This equals arr[3]

This is the #1 runtime error on the AP exam. Always check your loop bounds!

Arrays of Objects

// Array of String objects
String[] words = new String[3];
// words = [null, null, null] - NOT empty strings!

words[0] = "Hello";
words[1] = "World";
// words = ["Hello", "World", null]

// Calling methods on null causes NullPointerException!
words[2].length()  // CRASH! words[2] is null

// Safe pattern: check for null first
if (words[2] != null)
{
    System.out.println(words[2].length());
}
Key Concepts for the Exam
  • Array size is FIXED once created - you cannot add or remove elements
  • Use arr.length (no parentheses) to get size
  • Indices go from 0 to length - 1
  • Object arrays initialize to null, not empty objects
  • Arrays can hold primitives OR objects, but not both in the same array

Array Traversals

Traversing an array means visiting each element, typically to read, process, or modify the values. There are several traversal patterns you need to know.

Pattern 1: Standard for Loop

Use when you need the index, need to modify elements, or need to access adjacent elements.

int[] arr = {10, 20, 30, 40, 50};

// Forward traversal (most common)
for (int i = 0; i < arr.length; i++)
{
    System.out.println("Index " + i + ": " + arr[i]);
}
// Output:
// Index 0: 10
// Index 1: 20
// Index 2: 30
// Index 3: 40
// Index 4: 50
Loop Bounds: Use < not <=
for (int i = 0; i < arr.length; i++)   // ✔ CORRECT
for (int i = 0; i <= arr.length; i++)  // WRONG - causes crash!

If arr.length is 5, then i <= 5 tries to access arr[5], which doesn't exist!

Pattern 2: Enhanced for Loop (for-each)

Use when you only need to READ values and don't need the index.

int[] arr = {10, 20, 30, 40, 50};

// Enhanced for loop - simpler syntax for reading
for (int num : arr)
{
    System.out.println(num);
}
// Output: 10, 20, 30, 40, 50 (each on new line)

// Read as: "for each int num in arr"
Enhanced for Loop Limitation: Cannot Modify!
int[] arr = {10, 20, 30};

// This does NOT modify the array!
for (int num : arr)
{
    num = num * 2;  // Only changes the local copy!
}
// arr is STILL [10, 20, 30] - unchanged!

// To modify, you MUST use standard for loop:
for (int i = 0; i < arr.length; i++)
{
    arr[i] = arr[i] * 2;  // This DOES modify the array
}
// arr is now [20, 40, 60]

The variable in an enhanced for loop is a copy of each element, not a reference to it!

Pattern 3: Backward Traversal

Essential for certain algorithms (like removing from ArrayList).

int[] arr = {10, 20, 30, 40, 50};

// Start at last index, go down to 0
for (int i = arr.length - 1; i >= 0; i--)
{
    System.out.println(arr[i]);
}
// Output: 50, 40, 30, 20, 10

Pattern 4: Partial Traversal

int[] arr = {10, 20, 30, 40, 50, 60};

// First half only
for (int i = 0; i < arr.length / 2; i++)
{
    System.out.print(arr[i] + " ");
}
// Output: 10 20 30

// Second half only
for (int i = arr.length / 2; i < arr.length; i++)
{
    System.out.print(arr[i] + " ");
}
// Output: 40 50 60

// Every other element (even indices)
for (int i = 0; i < arr.length; i += 2)
{
    System.out.print(arr[i] + " ");
}
// Output: 10 30 50

// Every other element (odd indices)
for (int i = 1; i < arr.length; i += 2)
{
    System.out.print(arr[i] + " ");
}
// Output: 20 40 60

Pattern 5: Accessing Adjacent Elements

int[] arr = {10, 20, 30, 40, 50};

// Compare each element with the next one
for (int i = 0; i < arr.length - 1; i++)  // Note: length - 1!
{
    if (arr[i] < arr[i + 1])
    {
        System.out.println(arr[i] + " < " + arr[i + 1]);
    }
}

// Compare each element with the previous one
for (int i = 1; i < arr.length; i++)  // Note: start at 1!
{
    if (arr[i] > arr[i - 1])
    {
        System.out.println(arr[i] + " > " + arr[i - 1]);
    }
}
When to Use Which Loop?
Situation Use
Just reading values Enhanced for loop
Need the index Standard for loop
Modifying elements Standard for loop
Comparing adjacent elements Standard for loop
Traversing backward Standard for loop
Skipping elements (every other) Standard for loop

Traversal with Strings

String[] words = {"apple", "banana", "cherry"};

// Using enhanced for loop
for (String word : words)
{
    System.out.println(word.toUpperCase());
}
// Output: APPLE, BANANA, CHERRY

// Check for null before calling methods!
String[] mixed = {"hello", null, "world"};
for (String s : mixed)
{
    if (s != null)  // Prevent NullPointerException
    {
        System.out.println(s.length());
    }
}

Array Algorithms

These standard algorithms appear constantly on the AP exam. Memorize these patterns!

Algorithm 1: Sum of Elements

int[] arr = {10, 20, 30, 40, 50};

int sum = 0;  // Accumulator starts at 0
for (int num : arr)
{
    sum = sum + num;  // Or: sum += num;
}
System.out.println(sum);  // 150

Algorithm 2: Average of Elements

int[] arr = {10, 20, 30, 40, 50};

int sum = 0;
for (int num : arr)
{
    sum += num;
}

// IMPORTANT: Cast to double for decimal result!
double average = (double) sum / arr.length;
System.out.println(average);  // 30.0

// Without cast: 150 / 5 = 30 (integer division)
// With cast: 150.0 / 5 = 30.0 (decimal division)

Algorithm 3: Find Maximum

int[] arr = {23, 45, 12, 67, 34};

// Initialize to FIRST element, not 0!
int max = arr[0];

for (int i = 1; i < arr.length; i++)  // Start at 1
{
    if (arr[i] > max)
    {
        max = arr[i];
    }
}
System.out.println(max);  // 67
Don't Initialize max to 0!
int[] arr = {-5, -3, -8, -1};

int max = 0;  // WRONG! What if all elements are negative?
// max would remain 0, which isn't even in the array!

int max = arr[0];  // ✔ CORRECT! Start with actual element
// max will correctly become -1

Algorithm 4: Find Minimum

int[] arr = {23, 45, 12, 67, 34};

int min = arr[0];

for (int i = 1; i < arr.length; i++)
{
    if (arr[i] < min)  // Just change > to <
    {
        min = arr[i];
    }
}
System.out.println(min);  // 12

Algorithm 5: Count Occurrences

int[] arr = {5, 3, 5, 7, 5, 2, 5};
int target = 5;

int count = 0;
for (int num : arr)
{
    if (num == target)
    {
        count++;
    }
}
System.out.println(count);  // 4

Algorithm 6: Count Elements Meeting Condition

int[] arr = {12, 7, 25, 3, 18, 9};

// Count even numbers
int evenCount = 0;
for (int num : arr)
{
    if (num % 2 == 0)
    {
        evenCount++;
    }
}
System.out.println(evenCount);  // 3 (12, 18, and implicitly checking others)

// Count numbers greater than 10
int bigCount = 0;
for (int num : arr)
{
    if (num > 10)
    {
        bigCount++;
    }
}
System.out.println(bigCount);  // 3 (12, 25, 18)

Algorithm 7: Check if Any Element Meets Condition

int[] arr = {12, 7, 25, 3, 18};

// Check if any element is negative
boolean hasNegative = false;
for (int num : arr)
{
    if (num < 0)
    {
        hasNegative = true;
        // Can break here for efficiency, but not required
    }
}
System.out.println(hasNegative);  // false

Algorithm 8: Check if ALL Elements Meet Condition

int[] arr = {12, 8, 24, 6, 18};

// Check if ALL elements are even
boolean allEven = true;  // Assume true, look for counterexample
for (int num : arr)
{
    if (num % 2 != 0)  // If any is NOT even
    {
        allEven = false;
    }
}
System.out.println(allEven);  // true

Algorithm 9: Shift Elements Left

int[] arr = {1, 2, 3, 4, 5};

// Shift all elements left by one position
// First element is lost, last position gets default/placeholder
for (int i = 0; i < arr.length - 1; i++)
{
    arr[i] = arr[i + 1];
}
arr[arr.length - 1] = 0;  // Or some default value
// arr = [2, 3, 4, 5, 0]

Algorithm 10: Shift Elements Right

int[] arr = {1, 2, 3, 4, 5};

// Shift all elements right by one position
// Last element is lost, first position gets new value
for (int i = arr.length - 1; i > 0; i--)  // Go backward!
{
    arr[i] = arr[i - 1];
}
arr[0] = 99;  // New value at front
// arr = [99, 1, 2, 3, 4]

Algorithm 11: Reverse an Array

int[] arr = {1, 2, 3, 4, 5};

// Swap elements from outside in
for (int i = 0; i < arr.length / 2; i++)
{
    // Swap arr[i] with arr[length - 1 - i]
    int temp = arr[i];
    arr[i] = arr[arr.length - 1 - i];
    arr[arr.length - 1 - i] = temp;
}
// arr = [5, 4, 3, 2, 1]

// Trace for arr = [1, 2, 3, 4, 5]:
// i=0: swap arr[0] and arr[4] → [5, 2, 3, 4, 1]
// i=1: swap arr[1] and arr[3] → [5, 4, 3, 2, 1]
// i=2: 2 is NOT < 5/2=2, so loop ends

Algorithm 12: Copy Array

int[] original = {1, 2, 3, 4, 5};

// Create new array and copy elements
int[] copy = new int[original.length];
for (int i = 0; i < original.length; i++)
{
    copy[i] = original[i];
}

// Now copy is independent of original
copy[0] = 99;
// copy = [99, 2, 3, 4, 5]
// original = [1, 2, 3, 4, 5] (unchanged)
Assignment Doesn't Copy!
int[] a = {1, 2, 3};
int[] b = a;  // b points to SAME array as a!

b[0] = 99;
System.out.println(a[0]);  // 99! a was also changed!

This creates an alias, not a copy. Both variables point to the same array.

Using Text Files NEW for 2025-2026

The College Board added file I/O to the curriculum! You'll use the File and Scanner classes to read data from text files.

Basic File Reading Pattern

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class FileDemo
{
    public static void main(String[] args) throws IOException
    {
        // Step 1: Create File object
        File myFile = new File("data.txt");
        
        // Step 2: Create Scanner to read from file
        Scanner input = new Scanner(myFile);
        
        // Step 3: Read data using a loop
        while (input.hasNext())
        {
            String line = input.nextLine();
            System.out.println(line);
        }
        
        // Step 4: Close the scanner
        input.close();
    }
}
throws IOException is REQUIRED

Any method that reads from a file must include throws IOException in its header. This tells Java that file operations might fail (file not found, permission denied, etc.).

Scanner Methods for Reading Files

Method Returns Description
hasNext() boolean Returns true if there's more data to read
nextLine() String Reads and returns the entire next line
next() String Reads and returns the next word (token)
nextInt() int Reads and returns the next integer
nextDouble() double Reads and returns the next double

Example: Reading Numbers from a File

Suppose numbers.txt contains:

10
25
30
15
40
public static void readNumbers() throws IOException
{
    File file = new File("numbers.txt");
    Scanner input = new Scanner(file);
    
    int sum = 0;
    int count = 0;
    
    while (input.hasNext())
    {
        int num = input.nextInt();
        sum += num;
        count++;
    }
    
    input.close();
    
    System.out.println("Sum: " + sum);        // Sum: 120
    System.out.println("Count: " + count);    // Count: 5
    System.out.println("Average: " + (double) sum / count);  // Average: 24.0
}

Example: Reading Mixed Data Types

Suppose students.txt contains:

Alice 95 3.8
Bob 87 3.2
Carol 92 3.6
public static void readStudents() throws IOException
{
    File file = new File("students.txt");
    Scanner input = new Scanner(file);
    
    while (input.hasNext())
    {
        String name = input.next();       // Read name (word)
        int score = input.nextInt();      // Read score (integer)
        double gpa = input.nextDouble();  // Read GPA (double)
        
        System.out.println(name + ": Score=" + score + ", GPA=" + gpa);
    }
    
    input.close();
}
// Output:
// Alice: Score=95, GPA=3.8
// Bob: Score=87, GPA=3.2
// Carol: Score=92, GPA=3.6

Example: Reading File Data into an ArrayList

public static ArrayList<Integer> loadNumbers(String filename) throws IOException
{
    ArrayList<Integer> numbers = new ArrayList<Integer>();
    
    File file = new File(filename);
    Scanner input = new Scanner(file);
    
    while (input.hasNext())
    {
        numbers.add(input.nextInt());  // Autoboxing: int → Integer
    }
    
    input.close();
    return numbers;
}

Example: Processing Each Line Separately

public static void processLines() throws IOException
{
    File file = new File("data.txt");
    Scanner input = new Scanner(file);
    
    int lineNumber = 1;
    while (input.hasNext())
    {
        String line = input.nextLine();
        System.out.println("Line " + lineNumber + ": " + line);
        lineNumber++;
    }
    
    input.close();
}
File I/O on the AP Exam

Expect questions that ask you to:

  • Read data from a file into an array or ArrayList
  • Process file data (sum, count, find max/min)
  • Understand the throws IOException clause
  • Use hasNext() as a loop condition

You won't need to handle exceptions with try-catch or write to files.

Wrapper Classes

ArrayLists can only hold objects, not primitive types. Wrapper classes let you wrap primitives in objects.

Primitive Types and Their Wrappers

Primitive Wrapper Class Example
int Integer Integer x = Integer.valueOf(5);
double Double Double y = Double.valueOf(3.14);
boolean Boolean Boolean b = Boolean.valueOf(true);

Autoboxing: Automatic Primitive → Object

// Java automatically converts primitives to wrapper objects
Integer num = 42;  // int 42 is automatically "boxed" into an Integer
Double price = 19.99;  // double is boxed into Double

// Works with ArrayList too!
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(10);  // int 10 is autoboxed to Integer
numbers.add(20);
numbers.add(30);

Unboxing: Automatic Object → Primitive

Integer numObj = 42;
int numPrim = numObj;  // Integer is automatically "unboxed" to int

// Works when getting from ArrayList
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(100);

int value = numbers.get(0);  // Integer is unboxed to int
int doubled = numbers.get(0) * 2;  // Unboxing happens automatically
NullPointerException with Unboxing
Integer num = null;
int x = num;  // CRASH! Can't unbox null!

// This can happen with ArrayList too:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(null);  // Legal - ArrayList can hold null
int val = list.get(0);  // CRASH! Trying to unbox null

Useful Integer Methods

// Parse a String to int
String s = "123";
int num = Integer.parseInt(s);  // num = 123

// Get maximum and minimum possible int values
int maxInt = Integer.MAX_VALUE;  // 2147483647
int minInt = Integer.MIN_VALUE;  // -2147483648

Useful Double Methods

// Parse a String to double
String s = "3.14159";
double pi = Double.parseDouble(s);  // pi = 3.14159

ArrayList

An ArrayList is a resizable array. Unlike arrays, you can add and remove elements.

Creating an ArrayList

import java.util.ArrayList;

ArrayList<String> names = new ArrayList<String>();
ArrayList<Integer> nums = new ArrayList<Integer>();

ArrayList Methods

Method Description
add(obj) Add to end
add(i, obj) Insert at index i
get(i) Get element at i
set(i, obj) Replace at i, returns old
remove(i) Remove at i, returns removed
size() Number of elements

Traced Example

ArrayList<String> list = new ArrayList<String>();
list.add("A");      // [A]
list.add("B");      // [A, B]
list.add("C");      // [A, B, C]
list.add(1, "X");  // [A, X, B, C]
list.set(0, "Z");   // [Z, X, B, C]
list.remove(2);     // [Z, X, C]

ArrayList Algorithms

#1 MISTAKE: Forward Removal Skips Elements!
// WRONG!
for (int i = 0; i < list.size(); i++)
    if (condition) list.remove(i);

// CORRECT - go backward!
for (int i = list.size()-1; i >= 0; i--)
    if (condition) list.remove(i);

Remove All Occurrences

public static void removeAll(ArrayList<String> list, String target)
{
    for (int i = list.size() - 1; i >= 0; i--)
        if (list.get(i).equals(target))
            list.remove(i);
}

Filter to New List

public static ArrayList<Integer> getEvens(ArrayList<Integer> nums)
{
    ArrayList<Integer> result = new ArrayList<Integer>();
    for (int n : nums)
        if (n % 2 == 0)
            result.add(n);
    return result;
}

² 2D Arrays

Creating 2D Arrays

int[][] grid = new int[3][4];  // 3 rows, 4 cols

int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
CRITICAL: [row][col] - Row First!
matrix[1][2]       // Row 1, Col 2 → 6
matrix.length      // Rows (3)
matrix[0].length   // Cols (3)

Row-Major Traversal

for (int r = 0; r < arr.length; r++)
    for (int c = 0; c < arr[0].length; c++)
        System.out.print(arr[r][c] + " ");

Column-Major Traversal

for (int c = 0; c < arr[0].length; c++)
    for (int r = 0; r < arr.length; r++)
        System.out.print(arr[r][c] + " ");

2D Array Algorithms

Sum All Elements

public static int sumAll(int[][] arr)
{
    int sum = 0;
    for (int r = 0; r < arr.length; r++)
        for (int c = 0; c < arr[0].length; c++)
            sum += arr[r][c];
    return sum;
}

Count Matching

public static int countPositive(int[][] arr)
{
    int count = 0;
    for (int r = 0; r < arr.length; r++)
        for (int c = 0; c < arr[0].length; c++)
            if (arr[r][c] > 0)
                count++;
    return count;
}

Process Single Row

public static int rowSum(int[][] arr, int row)
{
    int sum = 0;
    for (int c = 0; c < arr[0].length; c++)
        sum += arr[row][c];
    return sum;
}

Process Single Column

public static int colSum(int[][] arr, int col)
{
    int sum = 0;
    for (int r = 0; r < arr.length; r++)
        sum += arr[r][col];
    return sum;
}

Š Sorting Algorithms

Selection Sort

Find minimum, swap to front. Repeat.

public static void selectionSort(int[] arr)
{
    for (int i = 0; i < arr.length - 1; i++)
    {
        int minIdx = i;
        for (int j = i + 1; j < arr.length; j++)
            if (arr[j] < arr[minIdx])
                minIdx = j;
        // Swap
        int temp = arr[i];
        arr[i] = arr[minIdx];
        arr[minIdx] = temp;
    }
}

Selection Sort Trace

// [64, 25, 12, 22, 11]
// Pass 1: min=11 at idx 4, swap with idx 0 → [11, 25, 12, 22, 64]
// Pass 2: min=12 at idx 2, swap with idx 1 → [11, 12, 25, 22, 64]
// Pass 3: min=22 at idx 3, swap with idx 2 → [11, 12, 22, 25, 64]
// Pass 4: min=25 at idx 3, no swap needed → [11, 12, 22, 25, 64]

Insertion Sort

Build sorted portion by inserting each element in correct position.

public static void insertionSort(int[] arr)
{
    for (int i = 1; i < arr.length; i++)
    {
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key)
        {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}
Sort Best Worst
Selection
Insertion n

Recursion

A method that calls itself. Needs: base case + recursive case.

Factorial

public static int factorial(int n)
{
    if (n <= 1) return 1;       // Base case
    return n * factorial(n - 1);  // Recursive case
}
// factorial(5) = 5*4*3*2*1 = 120

Fibonacci

public static int fib(int n)
{
    if (n <= 1) return n;
    return fib(n - 1) + fib(n - 2);
}
// 0, 1, 1, 2, 3, 5, 8, 13...

Recursive Binary Search

public static int binSearch(int[] arr, int t, int lo, int hi)
{
    if (lo > hi) return -1;
    int mid = (lo + hi) / 2;
    if (arr[mid] == t) return mid;
    if (arr[mid] < t) return binSearch(arr, t, mid+1, hi);
    return binSearch(arr, t, lo, mid-1);
}
Common Recursion Errors
  • Missing base case → StackOverflowError
  • Not progressing toward base case
  • Forgetting return on recursive call

Common Exam Traps

1. Off-by-One


i <= arr.length

i < arr.length

2. length vs length() vs size()

Array arr.length
String str.length()
ArrayList list.size()

3. 2D Array [row][col]


grid[col][row]

grid[row][col]

4. String Comparison


str1 == str2

str1.equals(str2)

5. Enhanced for Can't Modify

for (int num : arr)
    num = num * 2;  // Doesn't change array!

6. Initialize max to arr[0], not 0

int max = 0;       // Fails for all-negative arrays
int max = arr[0];  // ✔ Correct

7. Binary Search Needs Sorted Data

int[] unsorted = {50, 10, 30};
binarySearch(unsorted, 30);  // Wrong result!

Practice Questions

Q1: Array Traversal

int[] arr = {2, 4, 6, 8, 10};
int sum = 0;
for (int i = 0; i < arr.length; i += 2)
    sum += arr[i];
System.out.println(sum);
B) 18
Indices 0,2,4: 2+6+10=18

Q2: Enhanced For Loop

int[] arr = {1, 2, 3};
for (int num : arr)
    num = num + 10;
System.out.println(arr[1]);
A) 2
Enhanced for loop doesn't modify the array.

Q3: 2D Array Access

int[][] grid = {{1,2,3}, {4,5,6}, {7,8,9}};
System.out.println(grid[2][0] + grid[0][2]);
B) 10
grid[2][0]=7, grid[0][2]=3, sum=10

Q4: ArrayList Operations

ArrayList<String> list = new ArrayList<String>();
list.add("A"); list.add("B"); list.add("C");
list.add(1, "X");
list.remove(2);
System.out.println(list);
A) [A, X, C]
After adds: [A,B,C]. Insert X at 1: [A,X,B,C]. Remove idx 2: [A,X,C]

Q5: Recursion Trace

public static int mystery(int n) {
    if (n <= 0) return 0;
    return 1 + mystery(n - 2);
}
System.out.println(mystery(7));
B) 4
m(7)=1+m(5)=1+1+m(3)=1+1+1+m(1)=1+1+1+1+m(-1)=4+0=4

Q6: Fibonacci

public static int fib(int n) {
    if (n <= 1) return n;
    return fib(n-1) + fib(n-2);
}
System.out.println(fib(6));
B) 8
Sequence: 0,1,1,2,3,5,8... fib(6)=8

Q7: Binary Search Comparisons

int[] arr = {10, 20, 30, 40, 50, 60, 70, 80}; // Find 30

How many comparisons to find 30 with binary search?

B) 3
mid=3(40)→left, mid=1(20)→right, mid=2(30)→found

Q8: Selection Sort Pass

int[] arr = {64, 25, 12, 22, 11};

After ONE pass of selection sort:

A) [11, 25, 12, 22, 64]
Find min (11), swap with first element (64)

Q9: Which Search?

Array is UNSORTED with 1000 elements. Which search?

B) Linear search
Binary search requires sorted data!

Q10: ArrayList Removal Bug

ArrayList<Integer> list = ...; // [1, 2, 3, 4]
for (int i = 0; i < list.size(); i++)
    if (list.get(i) % 2 == 0)
        list.remove(i);
System.out.println(list);
A) [1, 3]
Forward removal bug! After removing 2, 4 shifts to index 1 but i=2, so 3 is at index 1 and gets skipped over but 4 at new position gets removed.

Q11: File I/O

Which is required when reading from a file with Scanner?

B) throws IOException
File operations may fail, so Java requires handling with throws or try-catch.

Q12: Wrapper Class

Integer x = null;
int y = x + 5;

What happens?

C) NullPointerException
Can't unbox null to int.

FRQ Practice

FRQ 1: ArrayList Processing (FRQ #3 Style)

Part A: Write countAbove that returns how many scores are above a threshold.

public static int countAbove(ArrayList<Integer> scores, int threshold)

Part B: Write removeBelow that removes all scores below a passing grade.

public static void removeBelow(ArrayList<Integer> scores, int passing)
Part A:
public static int countAbove(ArrayList<Integer> scores, int threshold)
{
    int count = 0;
    for (int score : scores)
        if (score > threshold)
            count++;
    return count;
}
Part B:
public static void removeBelow(ArrayList<Integer> scores, int passing)
{
    for (int i = scores.size() - 1; i >= 0; i--)
        if (scores.get(i) < passing)
            scores.remove(i);
}
Rubric (Part B - 5 pts)

+1 Traverses backward

+1 Uses get(i) correctly

+1 Compares to passing

+1 Uses remove(i)

+1 No elements skipped

FRQ 2: 2D Array Processing (FRQ #4 Style)

Part A: Write countEmpty that returns how many null elements are in a 2D String array.

public static int countEmpty(String[][] chart)

Part B: Write getColumn that returns an ArrayList of all non-null elements in a column.

public static ArrayList<String> getColumn(String[][] chart, int col)
Part A:
public static int countEmpty(String[][] chart)
{
    int count = 0;
    for (int r = 0; r < chart.length; r++)
        for (int c = 0; c < chart[0].length; c++)
            if (chart[r][c] == null)
                count++;
    return count;
}
Part B:
public static ArrayList<String> getColumn(String[][] chart, int col)
{
    ArrayList<String> result = new ArrayList<String>();
    for (int r = 0; r < chart.length; r++)
        if (chart[r][col] != null)
            result.add(chart[r][col]);
    return result;
}
Rubric (Part A - 4 pts)

+1 Nested loops

+1 Correct bounds

+1 Checks for null

+1 Returns count

FRQ 3: File I/O (NEW Topic!)

Write loadData that reads integers from a file into an ArrayList.

public static ArrayList<Integer> loadData(String filename) throws IOException
public static ArrayList<Integer> loadData(String filename) throws IOException
{
    ArrayList<Integer> data = new ArrayList<Integer>();
    File file = new File(filename);
    Scanner input = new Scanner(file);
    
    while (input.hasNext())
        data.add(input.nextInt());
    
    input.close();
    return data;
}

Quick Reference

Essential Syntax

Structure Create Access Size
Array new int[5] arr[0] arr.length
ArrayList new ArrayList() list.get(0) list.size()
2D Array new int[3][4] grid[r][c] grid.length, grid[0].length

Algorithm Complexity

Algorithm Best Worst Note
Linear Search 1 n Any array
Binary Search 1 log n Sorted only!
Selection Sort
Insertion Sort n Best when nearly sorted

Final Checklist

  • < not <= for loop bounds
  • .length / .length() / .size()
  • grid[row][col] not grid[col][row]
  • Remove from ArrayList BACKWARD
  • .equals() for Strings
  • Binary search = sorted only
  • Initialize max/min to first element
  • Enhanced for can't modify
  • Check for null before method calls
  • throws IOException for files

AP CSA Unit 4: Data Collections

Ultimate Study Guide - 2025-2026

© AP CS Exam Prep | Good luck!

Contact form