ArrayList & Collections

Arrays solve the problem of holding several values under one name, but only if you know exactly how many you'll need before you start. Real programs rarely know that in advance — you don't know how many students will enroll or how many items will end up in a cart. ArrayList is a list that grows and shrinks as you use it.

Creating and filling an ArrayList

ArrayList lives in java.util, so it needs an import. It's also generic — the type in angle brackets, like <String>, tells Java what kind of elements this particular list is allowed to hold, and the compiler enforces that consistently.

</> RosterDemo.java
import java.util.ArrayList;

public class RosterDemo {
    public static void main(String[] args) {
        ArrayList<String> roster = new ArrayList<>();
        roster.add("Wren");
        roster.add("Talia");
        roster.add("Devon");

        System.out.println(roster);
        System.out.println("Enrolled: " + roster.size());
    }
}
Output
[Wren, Talia, Devon]
Output (continued)
Enrolled: 3

Printing an ArrayList directly gives you a readable, bracketed listing of its contents for free — unlike an array, which would print something unreadable like [Ljava.lang.String;@1b6d3586 if you tried the same thing with System.out.println. There's no equivalent line-count field either; you always ask for the size with .size(), a method call, not a field.

Reading, updating, and removing elements

ArrayList uses the same zero-based indexing as an array, but through method calls instead of square-bracket syntax:

</> GradeTracker.java
import java.util.ArrayList;

public class GradeTracker {
    public static void main(String[] args) {
        ArrayList<Integer> scores = new ArrayList<>();
        scores.add(88);
        scores.add(74);
        scores.add(91);

        scores.set(1, 79); // correcting the second score
        scores.remove(0);  // dropping the first score entirely

        System.out.println(scores);
        System.out.println("First remaining score: " + scores.get(0));
    }
}
Output
[79, 91]
First remaining score: 79

scores.remove(0) deletes the element at index 0 and shifts everything after it down by one — the list closes the gap automatically, which is exactly the kind of bookkeeping you'd have to do by hand with a plain array.

Integer, not int

Notice the list above is declared ArrayList<Integer>, not ArrayList<int>. Generics in Java only work with object types, and the eight primitives aren't objects — so each primitive type has a corresponding wrapper class (int pairs with Integer, double with Double, boolean with Boolean). Java converts between them for you automatically wherever it can, a process called autoboxing, which is why writing scores.add(88) above worked without you ever mentioning Integer by name.

Looping over a list

The enhanced for loop works on an ArrayList exactly the way it works on an array:

</> AverageScore.java
import java.util.ArrayList;

public class AverageScore {
    public static void main(String[] args) {
        ArrayList<Integer> scores = new ArrayList<>();
        scores.add(79);
        scores.add(91);
        scores.add(85);

        int total = 0;
        for (int score : scores) {
            total += score;
        }

        double average = (double) total / scores.size();
        System.out.println("Class average: " + average);
    }
}
Output
Class average: 85.0

A brief word on maps

Once you find yourself wanting to look something up by name rather than by position — a student's grade by their name, an item's price by its SKU — an ArrayList stops being the right tool, since finding something in it means checking each element in order. HashMap<K, V>, also in java.util, stores key-value pairs and can look up a value by its key almost instantly: HashMap<String, Integer> gradebook = new HashMap<>(); gradebook.put("Wren", 88); gradebook.get("Wren"); hands back 88 directly, no searching required. It's worth knowing this exists as your next step once lists start feeling limiting.

Note: arrays and ArrayList aren't rivals so much as tools for different situations — reach for an array when the size is fixed and known, and performance in tight loops matters most; reach for ArrayList whenever the collection needs to grow, shrink, or you'd rather not think about sizing it up front at all. Most everyday application code leans on ArrayList and its relatives far more often than on raw arrays.