Fiveable

💻AP Computer Science A Unit 4 Review

QR code for AP Computer Science A practice questions

4.9 Traversing ArrayLists

4.9 Traversing ArrayLists

Written by the Fiveable Content Team • Last updated June 2026
Verified for the 2027 exam
Verified for the 2027 examWritten by the Fiveable Content Team • Last updated June 2026
💻AP Computer Science A
Unit & Topic Study Guides

Frequently Asked Questions

Previous Exam Prep

Study Tools

Exam Skills

AP Cram Sessions 2021

Pep mascot

Traversing an ArrayList means using a loop or recursion to visit its elements in order. You can use an indexed for loop, a while loop, or an enhanced for loop, but you cannot safely add or remove elements during an enhanced for loop. For AP Computer Science A, choose the traversal style based on whether you only need to read elements or also modify the list.

Why This Matters for the AP Computer Science A Exam

ArrayList traversal shows up in both multiple-choice and free-response code writing. In multiple-choice, you often trace a loop to predict output or spot why a segment throws an exception or skips elements. In free-response, you write methods that analyze and manipulate an ArrayList of objects, and these methods frequently ask you to insert or remove elements, which means you have to adjust the loop counter so you do not skip or overshoot positions.

The skills tied to this topic include writing code that uses ArrayList traversals, explaining why a segment will not work as intended and fixing it, and describing what a segment of code does. Being fluent with both indexed loops and enhanced for loops gives you flexibility on whichever question type appears.

Key Takeaways

  • Traversing an ArrayList uses iteration or recursion to access all or part of its elements in order.
  • An indexed for loop or while loop uses get(index) and runs while the index is less than size().
  • An enhanced for loop reads each element in order but cannot safely add or remove elements.
  • Accessing an index outside 0 to size() - 1 throws an IndexOutOfBoundsException.
  • Adding or removing during an enhanced for loop traversal can throw a ConcurrentModificationException.
  • Removing during an indexed loop shifts later elements left, so you must adjust the counter to avoid skipping elements.

Core Concepts

Ways to Traverse an ArrayList

You have a few standard ways to move through an ArrayList. Each visits elements in order, but they differ in how much control you get.

An indexed for loop or a while loop uses the index directly. You call get(i) to read an element and run the loop while i < list.size(). This gives you full control, including the ability to modify elements with set or to remove elements when you handle the index carefully.

An enhanced for loop (also called a for-each loop) reads a copy of each element in order without using an index. It is cleaner for read-only work, but you do not have the index, and you should not change the list's size inside it.

Recursion can also traverse an ArrayList by processing one element and then calling the method again on the rest. This is another form of repetition you may see in tracing questions.

Index Range and Out-of-Bounds Access

Valid indices for an ArrayList run from 0 to size() - 1. Trying to read or write an index outside that range throws an IndexOutOfBoundsException. A common mistake is starting an index loop at size() instead of size() - 1, or letting the loop condition run one step too far.

Index Shifting After Removal

When you remove an element at index i, every element after it shifts left by one position, and the size drops by one. The element that used to be at i + 1 is now at i. If your loop then increments to i + 1, you jump over that shifted element and skip it.

Two reliable fixes for an indexed loop:

  • Loop backwards from size() - 1 down to 0. Removals only affect indices you have already passed, so nothing gets skipped.
  • After removing at index i, do not increment. Decrement i (or skip the increment) so the loop rechecks the position that the shifted element now occupies.

Inserting an element also shifts elements, but to the right, so the same care with the counter applies.

Why Enhanced For Loops Cannot Modify Size

An enhanced for loop is built for steady, read-only passes. If you add or remove elements during one, Java may throw a ConcurrentModificationException because the loop can no longer trust its position in the list. When you need to insert or delete during a traversal, switch to an indexed loop or collect the changes and apply them after the loop ends.

Code Examples

Enhanced For Loop: Clean Read-Only Traversal

</>Java
import java.util.ArrayList;

public class EnhancedForDemo {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<String>();
        fruits.add("apple");
        fruits.add("banana");
        fruits.add("cherry");
        fruits.add("date");

        // Enhanced for loop is ideal for read-only traversal
        for (String fruit : fruits) {
            System.out.println(fruit + " has " + fruit.length() + " letters");
        }

        // This would risk a ConcurrentModificationException:
        /*
        for (String fruit : fruits) {
            if (fruit.equals("banana")) {
                fruits.remove(fruit);  // do not modify size here
            }
        }
        */
    }
}

Use an enhanced for loop when you only need to look at each element. The syntax is clean and there is no index to manage.

Indexed For Loop: Full Control with set

</>Java
import java.util.ArrayList;

public class TraditionalForDemo {
    public static void main(String[] args) {
        ArrayList<Integer> grades = new ArrayList<Integer>();
        grades.add(85);
        grades.add(92);
        grades.add(78);
        grades.add(96);
        grades.add(73);

        for (int i = 0; i < grades.size(); i++) {
            int grade = grades.get(i);
            // set replaces an element without changing the size, so it is safe
            if (grade < 80) {
                grades.set(i, grade + 5);
            }
        }

        System.out.println("Final grades: " + grades);
    }
}

An indexed loop gives you the position, which you need for operations like set. Because set does not change the size, it never causes index shifting.

The Wrong Way to Remove Elements

</>Java
import java.util.ArrayList;

public class RemovalMistake {
    public static void main(String[] args) {
        ArrayList<String> words = new ArrayList<String>();
        words.add("hello");
        words.add("remove");
        words.add("world");
        words.add("remove");
        words.add("java");

        // BUG: removing during a forward loop skips elements
        for (int i = 0; i < words.size(); i++) {
            if (words.get(i).equals("remove")) {
                words.remove(i);
                // the next element shifts down to index i,
                // but i increments, so that element is skipped
            }
        }

        System.out.println("After (buggy): " + words);
        // Not all "remove" elements are gone
    }
}

When you remove at index i, the next element slides to i, but the loop moves to i + 1 and skips it.

Two Safe Ways to Remove Elements

</>Java
import java.util.ArrayList;

public class SafeRemoval {
    public static void main(String[] args) {
        ArrayList<String> words = new ArrayList<String>();
        words.add("hello");
        words.add("remove");
        words.add("world");
        words.add("remove");
        words.add("java");

        // Method 1: loop backwards so removals do not affect upcoming indices
        for (int i = words.size() - 1; i >= 0; i--) {
            if (words.get(i).equals("remove")) {
                words.remove(i);
            }
        }
        System.out.println("After backwards removal: " + words);

        // Reset for the second approach
        words.clear();
        words.add("keep");
        words.add("delete");
        words.add("keep");
        words.add("delete");

        // Method 2: decrement i after removing so the shifted element is rechecked
        for (int i = 0; i < words.size(); i++) {
            if (words.get(i).equals("delete")) {
                words.remove(i);
                i--;
            }
        }
        System.out.println("After index adjustment: " + words);
    }
}

Both methods avoid skipping. The backwards loop is often easier to reason about because you never have to adjust the counter mid-loop.

Building a New ArrayList During Traversal

</>Java
import java.util.ArrayList;

public class FilteringDemo {
    public static void main(String[] args) {
        ArrayList<Integer> allScores = new ArrayList<Integer>();
        allScores.add(95);
        allScores.add(67);
        allScores.add(88);
        allScores.add(72);
        allScores.add(91);
        allScores.add(55);

        ArrayList<Integer> passing = new ArrayList<Integer>();
        ArrayList<Integer> failing = new ArrayList<Integer>();

        // Reading the original list and writing to new lists is always safe
        for (Integer score : allScores) {
            if (score >= 70) {
                passing.add(score);
            } else {
                failing.add(score);
            }
        }

        System.out.println("Passing: " + passing);
        System.out.println("Failing: " + failing);
    }
}

Writing into new lists while reading the original is a clean way to filter without touching the list you are traversing.

Common Errors and Debugging

ConcurrentModificationException

This happens when you change an ArrayList's size during an enhanced for loop traversal.

</>Code
Exception in thread "main" java.util.ConcurrentModificationException

The usual cause is calling add or remove on the list inside an enhanced for loop. The fix is to switch to an indexed loop for the modification, or collect the changes and apply them after the loop finishes.

Index Shifting Bugs

These are quiet bugs where elements get skipped because the list shrank during a forward loop.

</>Java
// looks fine, but skips elements
for (int i = 0; i < list.size(); i++) {
    if (someCondition) {
        list.remove(i);  // shifts elements left, but i still increments
    }
}

Fix it with backwards iteration, or by decrementing i after a removal.

Off-by-One Errors in Backwards Loops

</>Java
// Wrong: starts at size() instead of size() - 1

for (int i = list.size(); i >= 0; i--) {
    System.out.println(list.get(i));  // IndexOutOfBoundsException
}

Valid indices run from 0 to size() - 1. Start a backwards loop at size() - 1, continue while i >= 0, and decrement with i--.

Practice Problems

Problem 1: Safe Element Removal

Write a method that removes all strings shorter than 4 characters from an ArrayList of strings without skipping any element.

</>Java
import java.util.ArrayList;

public class SafeRemovalPractice {
    // Backwards iteration (recommended)
    public static void removeShortStrings(ArrayList<String> words) {
        for (int i = words.size() - 1; i >= 0; i--) {
            if (words.get(i).length() < 4) {
                words.remove(i);
            }
        }
    }

    public static void main(String[] args) {
        ArrayList<String> testWords = new ArrayList<String>();
        testWords.add("cat");
        testWords.add("elephant");
        testWords.add("no");
        testWords.add("programming");
        testWords.add("hi");
        testWords.add("world");

        System.out.println("Before: " + testWords);
        removeShortStrings(testWords);
        System.out.println("After: " + testWords);
    }
}

Backwards iteration is a reliable choice because removals only touch indices you have already passed.

Problem 2: Data Processing with Indices

Write a method that replaces each element of an ArrayList of integers with the running sum up to that position. Print the index and new value for each element.

</>Java
import java.util.ArrayList;

public class RunningSumDemo {
    public static void calculateRunningSum(ArrayList<Integer> numbers) {
        int runningTotal = 0;
        for (int i = 0; i < numbers.size(); i++) {
            runningTotal += numbers.get(i);
            System.out.println("Index " + i + " -> " + runningTotal);
            numbers.set(i, runningTotal);
        }
    }

    public static void main(String[] args) {
        ArrayList<Integer> values = new ArrayList<Integer>();
        values.add(5);
        values.add(3);
        values.add(8);
        values.add(2);
        values.add(7);

        System.out.println("Original: " + values);
        calculateRunningSum(values);
        System.out.println("Final: " + values);
    }
}

This uses set to modify elements safely, since it does not change the list's size.

Problem 3: Traversal Method Comparison

Write two methods that return the index of the largest element in an ArrayList of integers, one using an indexed for loop and one using an enhanced for loop with manual index tracking.

</>Java
import java.util.ArrayList;

public class TraversalComparison {
    // Indexed loop: direct index access
    public static int findMaxIndexTraditional(ArrayList<Integer> numbers) {
        if (numbers.isEmpty()) return -1;

        int maxIndex = 0;
        for (int i = 1; i < numbers.size(); i++) {
            if (numbers.get(i) > numbers.get(maxIndex)) {
                maxIndex = i;
            }
        }
        return maxIndex;
    }

    // Enhanced loop: track the index yourself
    public static int findMaxIndexEnhanced(ArrayList<Integer> numbers) {
        if (numbers.isEmpty()) return -1;

        int maxIndex = 0;
        int currentIndex = 0;
        int maxValue = numbers.get(0);

        for (Integer value : numbers) {
            if (value > maxValue) {
                maxValue = value;
                maxIndex = currentIndex;
            }
            currentIndex++;
        }
        return maxIndex;
    }

    public static void main(String[] args) {
        ArrayList<Integer> testNumbers = new ArrayList<Integer>();
        testNumbers.add(15);
        testNumbers.add(8);
        testNumbers.add(23);
        testNumbers.add(42);
        testNumbers.add(16);
        testNumbers.add(31);

        System.out.println("Numbers: " + testNumbers);
        System.out.println("Indexed result: " + findMaxIndexTraditional(testNumbers));
        System.out.println("Enhanced result: " + findMaxIndexEnhanced(testNumbers));
    }
}

The enhanced loop needs a separate counter because it does not give you the index directly. The indexed loop has the position built in.

How to Use This on the AP Computer Science A Exam

Code Tracing

When you trace an ArrayList loop, write the list contents and the index next to each iteration. After any remove, redraw the list so you can see which element shifted into the open spot. This makes skipped-element bugs obvious instead of hidden.

Free Response

When a free-response method asks you to insert or remove elements, decide up front how you will protect the loop counter. Loop backwards for removals, or decrement the index after a removal in a forward loop. State the valid index range to yourself, 0 to size() - 1, before you write any get or remove call.

Common Trap

If a question shows an enhanced for loop that adds or removes from the same list, the expected answer is usually a runtime exception, not a clean result. Watch for that pattern.

Common Misconceptions

  • Enhanced for loops cannot edit the list's size. Reading and printing is fine, but adding or removing during one risks a ConcurrentModificationException.
  • Using set is not the same as adding or removing. set replaces a value in place and does not change the size, so it is safe in any loop type.
  • Removing an element does not leave a gap. The list closes up, shifting later elements left and reducing the size, which is exactly why forward removal loops skip elements.
  • Valid indices stop at size() - 1. Looping to size() or starting a backwards loop at size() throws an IndexOutOfBoundsException.
  • A buggy removal loop does not always crash. It often runs without error but quietly leaves some elements behind, so a clean run does not prove the logic is correct.

Vocabulary

The following words are mentioned explicitly in the College Board Course and Exam Description for this topic.

Term

Definition

ArrayList

A resizable array implementation in Java that can dynamically grow or shrink to store a collection of objects.

ConcurrentModificationException

An exception that occurs when the size of an ArrayList is changed while traversing it using an enhanced for loop.

enhanced for loop

A Java loop construct that iterates through all elements of a collection without using an index variable.

IndexOutOfBoundsException

An exception that occurs when attempting to access an index value outside the valid range of an ArrayList.

iteration

A form of repetition in which code is executed zero or more times based on a condition.

recursive statements

Programming statements that call themselves to process elements in a data structure.

traverse

To visit each element in a data structure (such as a string, array, or ArrayList) in a systematic way, often using recursion.

Frequently Asked Questions

What does it mean to traverse an ArrayList?

Traversing an ArrayList means using iteration or recursion to access all elements, or an ordered sequence of elements, in the list.

Which loop should I use to traverse an ArrayList?

Use an indexed for loop or while loop when you need the index, need to call set, or need to remove elements. Use an enhanced for loop for clean read-only traversal.

Why can removing elements in a forward loop skip items?

When you remove an element at index i, later elements shift left. If the loop then increments i, it skips the element that shifted into the current position.

How do you safely remove elements while traversing an ArrayList?

Two common AP CSA-safe methods are looping backward from size() - 1 to 0, or using an indexed forward loop and adjusting the index after a removal.

Can you add or remove elements in an enhanced for loop?

No. Changing the size of an ArrayList during an enhanced for loop can cause a ConcurrentModificationException, so use an indexed loop when the size may change.

What causes an IndexOutOfBoundsException with ArrayLists?

An IndexOutOfBoundsException happens when code tries to access an index outside the valid range from 0 to size() - 1.

Pep mascot
Upgrade your Fiveable account to print any study guide

Download study guides as beautiful PDFs See example

Print or share PDFs with your students

Always prints our latest, updated content

Mark up and annotate as you study

Click below to go to billing portal → update your plan → choose Yearly→ and select "Fiveable Share Plan". Only pay the difference

Plan is open to all students, teachers, parents, etc
Pep mascot
Upgrade your Fiveable account to export vocabulary

Download study guides as beautiful PDFs See example

Print or share PDFs with your students

Always prints our latest, updated content

Mark up and annotate as you study

Plan is open to all students, teachers, parents, etc
report an error
description

screenshots help us find and fix the issue faster (optional)

add screenshot