Conditional removal and replacement.
Sometimes you delete an element; sometimes you replace it with something better. Knowing which to choose — and how to combine them — is core to working with ArrayLists.
Two of the AP CSA ArrayList methods do very different things to the list's structure:
remove(int i)deletes the element at indexiand shifts everything after it left.set(int i, E obj)replaces the element at indexiwithout changing the list's size or shifting.
Many AP problems require a careful choice: remove the bad ones, or replace them with a sentinel? Or sometimes both, depending on a condition.
On the exam, this pattern appears in MCQs about size changes and in FRQs that ask for "clean-up" methods on object lists.
Remove shrinks; set replaces.
Pick based on whether the list should change size.
Conditional removal — iterate backwards
for (int i = list.size() - 1; i >= 0; i--) {
if (shouldRemove(list.get(i))) {
list.remove(i);
}
}
Backwards iteration is essential because remove shifts later elements left. By starting at the end, you never visit a shifted position.
Conditional set — direction doesn't matter
for (int i = 0; i < list.size(); i++) {
if (shouldReplace(list.get(i))) {
list.set(i, replacement);
}
}
set doesn't shift; the list keeps its size. Forward iteration is fine.
Combined: remove some, replace others
for (int i = list.size() - 1; i >= 0; i--) {
Item item = list.get(i);
if (item.isExpired()) {
list.remove(i); // delete
} else if (item.isStale()) {
list.set(i, new Item("fresh")); // replace
}
}
Because the loop runs backwards, removal still works correctly. set works the same in either direction, so combining is safe.
Choosing between them
- Drop the element from the collection? →
remove. - Keep the position but change the value? →
set. - The prompt says "replace with"? →
set. - The prompt says "delete" or "remove"? →
remove.
Vocabulary for structural changes.
Used in any list-modification FRQ.
- Conditional removal — deleting only elements that match a criterion.
- Conditional replacement — substituting an element when it matches a criterion.
- Shift — what
removedoes to later elements; whatsetdoes not. - Sentinel value — a stand-in (like
nullor a default object) used to mark something to ignore. - Backward iteration — looping from
size() - 1down to 0 for safe removal. - In-place replacement — using
setto swap one element for another at the same index.
How removal and replacement are tested.
Size changes and shift behavior are the dominant trap categories.
MCQ patterns to expect:
- "What is the list's size after this loop?" Trace each
removeandset; remove shrinks, set doesn't. - "Which elements were skipped?" A forward loop with
removeskips the element that takes the removed slot. - "Which operation is appropriate?" Read the prompt's verb: "remove" →
remove, "replace" →set.
FRQ tip: when combining both operations, iterate backwards. Backward iteration is safe for set and required for remove — it satisfies both at once.
Clean up a sensor reading list.
Remove invalid readings; clamp extreme valid ones.
Problem. Given ArrayList<Integer> readings: remove negative values (sensor errors); replace any value above 100 with exactly 100 (clamp).
public void cleanUp(ArrayList<Integer> readings) {
for (int i = readings.size() - 1; i >= 0; i--) {
int v = readings.get(i);
if (v < 0) {
readings.remove(i);
} else if (v > 100) {
readings.set(i, 100);
}
}
}
Trace. Start with [50, -3, 120, 80, -1, 200]. Iterate from index 5 down to 0:
- i = 5: value 200, > 100 → set to 100. List:
[50, -3, 120, 80, -1, 100]. - i = 4: value -1, < 0 → remove. List:
[50, -3, 120, 80, 100]. - i = 3: value 80, valid → no change.
- i = 2: value 120, > 100 → set to 100. List:
[50, -3, 120, 80, 100]→[50, -3, 100, 80, 100]. - i = 1: value -3, < 0 → remove. List:
[50, 100, 80, 100]. - i = 0: value 50, valid → no change.
Final. [50, 100, 80, 100].
Why this matters. Backward iteration kept indices stable even after removals. A forward loop would have skipped the element after each -3 and -1.
Errors that corrupt your list.
Most come from picking the wrong method or wrong direction.
- Forward loop with
remove. Skips the element that takes the removed slot. Use backward iteration. - Using
removewhen you shouldset. Shrinks the list when the prompt wanted size preserved. - Using
setwhen you shouldremove. Leaves a leftover element instead of dropping it. - Mismatched index after combined operations. Mixing forward and backward indices inside one loop confuses logic.
- Forgetting to update the loop bound.
list.size()in a forward loop changes after everyremove— yet another reason to iterate backwards.
Remove vs set decision table.
Pick the right tool before writing code.
Conditional Modify Reference
AP Quick Reference| Operation | List size | Iteration direction |
|---|---|---|
remove(i) |
Shrinks by 1 | Backwards (required) |
set(i, x) |
Unchanged | Either direction |
| Both combined | Shrinks only on remove | Backwards (covers both) |
| Prompt says "remove" | Drop the element | Use remove. |
| Prompt says "replace" | Keep the slot | Use set. |
How to choose and combine correctly.
Read the prompt's verbs; pick the method; pick the direction.
Use the three practice tools below this lesson in order:
- MCQ Practice — for each option, trace whether each operation changes the size. If a forward-loop with
removeappears, suspect a skipping bug. - Java Lab — write methods that clean up
ArrayList<Integer>data: remove negatives, replace big values. Always iterate backwards for safety. - FRQ Practice — underline the verbs ("remove", "replace") in the prompt. They map directly to
removeandset.
If you can pick the right method without hesitation, you've solved half the AP CSA list-modification problems.
Practice — attempt these now.
AP-style assessments aligned to this lesson. Time them.