ArrayList
IB Syllabus: B2.2.2 – Construct programs that apply ArrayLists: add, remove, and traverse elements in a dynamic list.
Table of Contents
- Key Concepts
- Core Operations
- Traversing an ArrayList
- Worked Examples
- Array vs ArrayList Comparison
- ArrayList of Objects
- Quick Check
- Trace Exercise
- Code Completion
- Spot the Error
- Predict the Output
- Practice Exercises
- Connections
Key Concepts
Why ArrayList?
Arrays have a fixed size – once created, they cannot grow or shrink. This is a problem when you do not know how many elements you will need at compile time.
String[] names = new String[5]; // exactly 5 slots -- what if we need 6?
An ArrayList is a dynamic list that grows and shrinks automatically. You can add elements without worrying about capacity, and remove elements without leaving gaps.
import java.util.ArrayList;
ArrayList<String> names = new ArrayList<>(); // starts empty, grows as needed
names.add("Alice"); // size is now 1
names.add("Bob"); // size is now 2
names.remove(0); // size is now 1
When to use an array: You know the exact size at creation time (e.g., days of the week, fixed grid). When to use an ArrayList: The size changes at runtime (e.g., student roster, shopping cart, search results).
Declaring an ArrayList
import java.util.ArrayList;
ArrayList<String> names = new ArrayList<>();
ArrayList<Integer> scores = new ArrayList<>();
ArrayList<Double> prices = new ArrayList<>();
Key syntax:
- Import
java.util.ArrayList - Specify the element type in angle brackets:
<String>,<Integer>,<Double> - Use
new ArrayList<>()with the diamond operator (Java infers the type)
Wrapper Types
ArrayLists store objects, not primitives. Java provides wrapper classes for each primitive type:
| Primitive | Wrapper Class |
|---|---|
int | Integer |
double | Double |
boolean | Boolean |
char | Character |
ArrayList<Integer> scores = new ArrayList<>(); // Integer, not int
scores.add(95); // Java auto-converts 95 to Integer (autoboxing)
int s = scores.get(0); // Java auto-converts Integer to int (unboxing)
Use Integer, not int, in the angle brackets. ArrayList<int> is a compile error.
Core Operations
Adding Elements
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple"); // adds to the end -> [Apple]
fruits.add("Banana"); // adds to the end -> [Apple, Banana]
fruits.add("Cherry"); // adds to the end -> [Apple, Banana, Cherry]
fruits.add(1, "Mango"); // inserts at index 1 -> [Apple, Mango, Banana, Cherry]
add(element) appends to the end. add(index, element) inserts at a specific position, shifting existing elements right.
Accessing Elements
String first = fruits.get(0); // "Apple"
String second = fruits.get(1); // "Mango"
Use .get(index), not [index]. Square bracket access does not work with ArrayList.
Updating Elements
fruits.set(1, "Pear"); // replaces index 1 -> [Apple, Pear, Banana, Cherry]
Removing Elements
fruits.remove(2); // removes by index -> [Apple, Pear, Cherry]
fruits.remove("Cherry"); // removes by value -> [Apple, Pear]
Removing shifts all elements after the removed one to the left. Indices of later elements change.
Size
int count = fruits.size(); // 2
Use .size(), not .length. Arrays use .length (no parentheses). ArrayLists use .size() (with parentheses). This is one of the most common mistakes.
Checking Contents
boolean hasPear = fruits.contains("Pear"); // true
int pos = fruits.indexOf("Apple"); // 0 (or -1 if not found)
Traversing an ArrayList
Standard for Loop
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
Enhanced for Loop (for-each)
for (String name : names) {
System.out.println(name);
}
The enhanced for loop is shorter but you cannot access the index or modify the list during traversal.
Removing During Traversal
Removing elements while looping forward causes problems because indices shift. Loop backwards instead:
for (int i = names.size() - 1; i >= 0; i--) {
if (names.get(i).equals("Bob")) {
names.remove(i);
}
}
Never remove elements in a forward loop without adjusting the index. You will skip elements or get an IndexOutOfBoundsException.
Worked Examples
Example 1: Student Roster
A teacher needs to manage a class list that changes as students join and leave.
import java.util.ArrayList;
public class ClassRoster {
public static void main(String[] args) {
ArrayList<String> students = new ArrayList<>();
// Students enroll
students.add("Alice");
students.add("Bob");
students.add("Charlie");
students.add("Diana");
System.out.println("Enrolled: " + students.size()); // 4
// Bob transfers out
students.remove("Bob");
System.out.println("After transfer: " + students.size()); // 3
// New student joins
students.add("Eve");
// Print the roster
for (int i = 0; i < students.size(); i++) {
System.out.println((i + 1) + ". " + students.get(i));
}
}
}
Output:
Enrolled: 4
After transfer: 3
1. Alice
2. Charlie
3. Diana
4. Eve
Example 2: Filtering a List
Find all scores above 80 from a list of test results.
public static ArrayList<Integer> getHighScores(ArrayList<Integer> scores) {
ArrayList<Integer> high = new ArrayList<>();
for (int i = 0; i < scores.size(); i++) {
if (scores.get(i) > 80) {
high.add(scores.get(i));
}
}
return high;
}
Example 3: Calculating an Average
public static double getAverage(ArrayList<Integer> scores) {
if (scores.size() == 0) {
return 0;
}
int total = 0;
for (int i = 0; i < scores.size(); i++) {
total += scores.get(i);
}
return (double) total / scores.size();
}
Array vs ArrayList Comparison
| Feature | Array | ArrayList |
|---|---|---|
| Size | Fixed at creation | Grows/shrinks dynamically |
| Declaration | int[] arr = new int[5]; | ArrayList<Integer> list = new ArrayList<>(); |
| Access | arr[i] | list.get(i) |
| Update | arr[i] = value; | list.set(i, value) |
| Length/Size | arr.length | list.size() |
| Add element | Not possible (fixed) | list.add(value) |
| Remove element | Not possible (fixed) | list.remove(index) |
| Stores primitives | Yes | No (uses wrapper classes) |
| Performance | Faster (direct memory) | Slightly slower (object overhead) |
Rule of thumb: Use arrays when the size is known and fixed. Use ArrayList when the size changes.
ArrayList of Objects
ArrayList works with any object type, including your own classes.
ArrayList<Student> roster = new ArrayList<>();
roster.add(new Student("Alice", 90));
roster.add(new Student("Bob", 85));
// Find a student by name
for (int i = 0; i < roster.size(); i++) {
if (roster.get(i).getName().equals("Alice")) {
System.out.println("Found: " + roster.get(i).getGrade());
}
}
This is the same pattern as using arrays of objects, but with get() instead of [i] and no need to track a separate count variable – .size() always returns the current number of elements.
Quick Check
Q1. Why does ArrayList<int> cause a compile error?
Q2. How do you get the number of elements in an ArrayList called items?
Q3. Given list = [Apple, Banana, Cherry], what is the list after list.remove(1)?
Q4. Given list = [Apple, Banana], what is the list after list.add(1, "Mango")?
Q5. Why should you loop backwards when removing elements from an ArrayList?
Trace Exercise
Trace the state of the ArrayList after each operation.
Trace: Track the contents and size of the ArrayList after each line.
ArrayList<String> list = new ArrayList<>();
list.add("Red"); // Line 1
list.add("Blue"); // Line 2
list.add("Green"); // Line 3
list.add(1, "Yellow"); // Line 4
list.remove(2); // Line 5
list.set(0, "Purple"); // Line 6| After Line | List Contents | Size |
|---|---|---|
| 1 | [Red] | 1 |
| 2 | [Red, Blue] | 2 |
| 3 | [Red, Blue, Green] | |
| 4 | ||
| 5 | ||
| 6 |
Code Completion
Complete the method that removes all occurrences of a value from an ArrayList.
Fill in the blanks: Remove all students with a failing grade (below 50).
public static void removeFailing(ArrayList<Integer> grades) {
for (int i = grades. - 1; i >= 0; i--) {
if (grades. < 50) {
grades.;
}
}
} Spot the Error
This code should print all names in the list, but it crashes.
Bug Hunt: This code does not compile. Find the error.
Pick the correct fix for line 2:
Predict the Output
Predict: What does this code print?
ArrayList<Integer> nums = new ArrayList<>();
nums.add(10);
nums.add(20);
nums.add(30);
nums.add(1, 40);
nums.remove(2);
System.out.println(nums.get(1)); Predict: What does this code print?
ArrayList<String> names = new ArrayList<>();
names.add("Apple");
names.add("Banana");
names.add("Cherry");
for (int i = names.size() - 1; i >= 0; i--) {
System.out.println(names.get(i));
} Practice Exercises
Core
-
Shopping cart – Create an
ArrayList<String>to represent a shopping cart. Add 5 items, remove one by name, print the remaining items and the total count. -
Score tracker – Create an
ArrayList<Integer>of test scores. Write a methodgetAverage(ArrayList<Integer> scores)that returns the average. Handle the empty list case. -
Search – Write a method
findIndex(ArrayList<String> list, String target)that returns the index oftarget, or -1 if not found. Do not use the built-inindexOfmethod.
Extension
-
Remove duplicates – Write a method that takes an
ArrayList<String>and removes all duplicate entries, keeping only the first occurrence of each value. -
Merge two lists – Write a method that takes two sorted
ArrayList<Integer>lists and returns a new sorted ArrayList containing all elements from both. Do not use any built-in sort method.
Challenge
- Inventory manager – Create a
Productclass (name, price, quantity) and manage anArrayList<Product>. Write methods to: add a product, remove by name, find the most expensive product, calculate total inventory value (price * quantity for all products), and list all products with quantity below a threshold.
Connections
- Prerequisites: 1D Arrays – fixed-size arrays and traversal
- Related: Strings –
.equals()for comparing String elements - Related: Exception Handling – IndexOutOfBoundsException on invalid index
- Forward: OOP Aggregation – ArrayList of objects in a container class
- Forward: Stacks – Stack uses similar CRUD patterns
- Forward: Queues – Queue uses similar CRUD patterns