Back

Activity 5.11 — Modifying ArrayLists Safely

divider

Introduction

Activity 5.11

Safe Removal While Traversing

Core Idea

  • Removing shifts elements left.
  • If you loop forward, you can skip elements.
  • This is a common AP exam trap.
// Core idea
// Removing shifts everything left.
nums.remove(i);
// element at i+1 moves to index i

Why forward loops fail

// Why forward loops fail
for (int i = 0; i < list.size(); i++)
{
if (condition)
{
list.remove(i);
// Next element shifts into index i
// But i will increment!
}
}

The Safe Pattern

// Safe removal pattern
for (int i = list.size() - 1; i >= 0; i--)
{
if (condition)
{
list.remove(i);
}
}
  • Start at the end.
  • Move backward.
  • Shifting does not affect unvisited elements.

For-each loops?

// Figure 4 — Using remove with for-each (NOT safe)
// This causes a runtime error.
for (int value : nums)
{
if (value % 2 == 0)
{
nums.remove(value); // dangerous
}
}
  • Modifying inside for-each causes runtime errors.
  • Use indexed loops when removing.

Today's Goals

  • Trace the bug.
  • Fix the bug.
  • Build filtering programs safely.

'F' → Fullscreen

Objectives

  • icon Explain why forward removal can skip elements.
  • icon Implement safe backward traversal removal.
  • icon Apply safe removal in practical filtering programs.
divider

Activity Tasks

  • icon Create a new project named Activity5_11_SafeRemoval.
  • icon Complete Tasks 1–4.
  • icon Test your logic carefully with different data sets.

Figures: Examples

Forward Removal Bug
// Figure 1 — Forward removal bug
import java.util.ArrayList;
public class Program
{
public static void main(String[] args)
{
ArrayList<Integer> nums = new ArrayList<Integer>();
nums.add(2);
nums.add(4);
nums.add(6);
nums.add(7);
for (int i = 0; i < nums.size(); i++)
{
if (nums.get(i) % 2 == 0)
{
nums.remove(i);
}
}
System.out.println(nums);
}
}
Safe Backward Removal
// Figure 3 — Correct backward traversal
import java.util.ArrayList;
public class Program
{
public static void main(String[] args)
{
ArrayList<Integer> nums = new ArrayList<Integer>();
nums.add(2);
nums.add(4);
nums.add(6);
nums.add(7);
for (int i = nums.size() - 1; i >= 0; i--)
{
if (nums.get(i) % 2 == 0)
{
nums.remove(i);
}
}
System.out.println(nums);
}
}

Task 1: Trace the Bug

Task 1 — Trace
// Task 1 — Trace the Bug
//
// Given this list:
// [2, 4, 6, 7]
//
// And this code:
//
// for (int i = 0; i < nums.size(); i++)
// {
// if (nums.get(i) % 2 == 0)
// {
// nums.remove(i);
// }
// }
//
// 1) Trace the list step-by-step.
// 2) What is the final list?
// 3) Which element was skipped?
// Write your trace as comments below.

Task 2: Fix the Code

Task 2 — Fix
// Task 2 — Fix the Code
//
// Rewrite the loop from Task 1 so that
// it correctly removes all even numbers.
//
// Then test on:
// [2, 4, 6, 7, 8, 10]
//
// Print the final list.
import java.util.ArrayList;
public class Program
{
public static void main(String[] args)
{
ArrayList<Integer> nums = new ArrayList<Integer>();
nums.add(2);
nums.add(4);
nums.add(6);
nums.add(7);
nums.add(8);
nums.add(10);
// Write your fixed loop here
System.out.println(nums);
}
}

Task 3: Word Filter

Task 3 — Filter Words
// Task 3 — Filter App (Practical)
//
// Create an ArrayList<String> of words.
// Add at least 8 words of varying lengths.
//
// Remove all words shorter than 4 characters.
//
// Print the list before and after filtering.
//
// IMPORTANT: Use the safe backward loop pattern.
import java.util.ArrayList;
public class Program
{
public static void main(String[] args)
{
ArrayList<String> words = new ArrayList<String>();
words.add("cat");
words.add("house");
words.add("sun");
words.add("computer");
words.add("pen");
words.add("keyboard");
words.add("tree");
words.add("mouse");
System.out.println("Before: " + words);
// Remove words shorter than 4 characters
System.out.println("After: " + words);
}
}

Task 4: Remove Failing Grades

Task 4 — Remove Grades
// Task 4 — Remove Failing Grades
//
// Create an ArrayList<Integer> grades.
// Add at least 10 grades.
//
// Remove all grades below 70.
//
// Print:
// - Original list
// - Filtered list
// - How many grades were removed
//
// Hint: Keep a counter.
import java.util.ArrayList;
public class Program
{
public static void main(String[] args)
{
ArrayList<Integer> grades = new ArrayList<Integer>();
grades.add(85);
grades.add(62);
grades.add(90);
grades.add(74);
grades.add(55);
grades.add(88);
grades.add(69);
grades.add(95);
grades.add(72);
grades.add(60);
System.out.println("Original: " + grades);
int removed = 0;
// Write safe removal loop here
System.out.println("Filtered: " + grades);
System.out.println("Removed count: " + removed);
}
}
divider

Sample Output

Sample Output
Before: [cat, house, sun, computer, pen, keyboard, tree, mouse]
After: [house, computer, keyboard, tree, mouse]
Original: [85, 62, 90, 74, 55, 88, 69, 95, 72, 60]
Filtered: [85, 90, 74, 88, 95, 72]
Removed count: 4
divider

Reflection Questions

  1. Why does forward removal skip elements?
  2. Why does backward traversal fix the problem?
  3. Why should you avoid removing items inside a for-each loop?
  4. What real-world situation might require filtering a list?
divider

Submission

Submit your completed activity.

Activity Complete