Verified for the 2025 AP Computer Science A exam•Citation:
Arrays are powerful, but they have limitations—particularly their fixed size. The ArrayList
class gives us a more flexible alternative that can grow or shrink as needed. In this guide, we'll explore how ArrayList
works and why it's such a useful tool for managing collections of objects.
An ArrayList
is a built-in Java class that stores a list of objects. Unlike regular arrays, an ArrayList
:
Think of an ArrayList
like a smarter, more flexible array that can adjust its capacity as you add or remove elements.
Unlike regular arrays, ArrayList
objects are mutable, which means you can:
ArrayList<String> names = new ArrayList<String>(); names.add("Alice"); // Add an element names.remove(0); // Remove an element names.add("Bob"); names.set(0, "Charlie"); // Change an element
ArrayList
can only store references to objects, not primitive types like int
, double
, or boolean
. For example:
// This works - String is an object type ArrayList<String> words = new ArrayList<String>(); // This won't work - int is a primitive type // ArrayList<int> numbers = new ArrayList<int>(); // ERROR!
To store primitive values, you must use wrapper classes:
Primitive Type | Wrapper Class |
---|---|
int | Integer |
double | Double |
boolean | Boolean |
char | Character |
// This works - using the Integer wrapper class ArrayList<Integer> numbers = new ArrayList<Integer>(); numbers.add(42); // Java automatically converts (autoboxes) int to Integer
To create an empty ArrayList
, use the constructor:
// Creates an empty ArrayList that will store String objects ArrayList<String> names = new ArrayList<String>();
The part between the angle brackets <>
is the generic type parameter, which specifies what type of objects this ArrayList
will store.
Before using ArrayList
, you need to import it from the Java utility package:
import java.util.ArrayList;
Add this line at the top of your file, before your class definition.
Generics allow you to specify what type of objects an ArrayList
can contain. The syntax uses angle brackets <>
with a type parameter:
ArrayList<E>
Where E
is a placeholder for the actual type you want to store.
When you create an ArrayList
, replace E
with the actual type:
// An ArrayList that stores Strings ArrayList<String> cities = new ArrayList<String>(); // An ArrayList that stores Integer objects ArrayList<Integer> scores = new ArrayList<Integer>(); // An ArrayList that stores Student objects ArrayList<Student> students = new ArrayList<Student>();
Using generics with ArrayList<E>
is preferred over the raw type ArrayList
because:
ClassCastException
errors that might occur with raw types// With generics - type safe, no casting needed ArrayList<String> names = new ArrayList<String>(); names.add("Alex"); String name = names.get(0); // No casting needed // Without generics (not recommended) ArrayList rawList = new ArrayList(); rawList.add("Alex"); String str = (String) rawList.get(0); // Casting required and might fail
Here's a complete example showing the basics of ArrayList
:
import java.util.ArrayList; public class StudentRoster { public static void main(String[] args) { // Create an ArrayList to store student names ArrayList<String> students = new ArrayList<String>(); // Add students students.add("Maria"); students.add("Juan"); students.add("Lee"); // Print the list size System.out.println("Number of students: " + students.size()); // Access elements System.out.println("First student: " + students.get(0)); // Modify an element students.set(1, "John"); // Print all students System.out.println("Updated student list:"); for (String student : students) { System.out.println("- " + student); } // Remove a student students.remove(2); // Check if list contains a student if (students.contains("Maria")) { System.out.println("Maria is in the class."); } // Clear the list students.clear(); System.out.println("Students after clearing: " + students.size()); } }
Feature | ArrayList | Array |
---|---|---|
Size | Dynamic (can grow/shrink) | Fixed (cannot change after creation) |
Type of elements | Objects only (uses wrapper classes for primitives) | Any type (primitives or objects) |
Methods | Many built-in methods (add, remove, etc.) | No built-in methods |
Memory usage | More overhead (but more convenient) | More efficient (but less flexible) |
Syntax | ArrayList<Type> name = new ArrayList<Type>(); | Type[] name = new Type[size]; |
Access | Methods: get(index) , set(index, value) | Direct: array[index] , array[index] = value |
ArrayList
is best when:
Arrays are better when:
The ArrayList
class offers a flexible, resizable alternative to fixed-size arrays. It stores object references (not primitives) and provides many helpful methods for adding, removing, and manipulating elements. Using generics (ArrayList<E>
) ensures type safety and helps prevent errors. While arrays are still useful in certain scenarios, ArrayList
is often the better choice when you need a dynamic collection of objects that can grow or shrink as your program runs.