Arrays and Collections
Storing many values together — fixed-size arrays, growable ArrayLists, and iterating over them safely
A single variable holds a single value. Real programs need to hold
many values — a list of orders, the lines of a file, the players
in a game. Java's two foundational tools are arrays and the
collections framework, starting with ArrayList.
Arrays: fixed-size, primitive-friendly
An array is a contiguous block of values of the same type. Its size is fixed at creation time and cannot change later.
Key facts about arrays:
- Indexed from
0tolength - 1. Going outside throwsArrayIndexOutOfBoundsException. .lengthis a field, not a method (no parentheses).- Arrays can hold primitives (
int[],double[]) or references (String[],Account[]). - The size is set once. To grow, you must allocate a bigger array and copy.
ArrayList: growable, generic
In real code, you almost always reach for an ArrayList
instead of a bare array. It can grow and shrink, has a rich set of
operations, and is part of Java's broader Collections Framework.
A few things to notice:
- We declared the variable as
List<String>, the interface, notArrayList<String>. We learned why in the interfaces chapter. <String>is a generic type parameter that tells the compiler this list holds Strings. Trying totodo.add(42)would not compile.add,remove,get,size,contains,isEmptyare the basic methods you'll use constantly.
The shape of the Collections Framework
For this page we focus on List (and especially ArrayList). The
next page is dedicated to Map and Set.
Iterating over a collection
The for-each loop works on anything that implements Iterable,
which includes every collection and every array:
for (String task : todo) {
System.out.println(task);
}Use the for-each form whenever you don't need the index. Use the
classic for (int i = 0; i < list.size(); i++) form when you do.
A common pitfall: modifying while iterating
You may not add to or remove from a collection inside a for-each
loop over it — doing so throws ConcurrentModificationException.
for (String task : todo) {
if (task.startsWith("learn")) {
todo.remove(task); // ❌ throws at runtime
}
}Two safe fixes:
- Iterate over a copy:
for (String task : new ArrayList<>(todo)). - Use an
Iteratorexplicitly and calliterator.remove().
A worked example: averaging a list of scores
List.of(...) produces an immutable list — perfect for "just a
bag of values I won't change."
Arrays vs ArrayList — when to use which?
| Array | ArrayList | |
|---|---|---|
| Size | Fixed at creation | Grows on demand |
| Can hold primitives directly | Yes (int[]) | No — must use wrapper (List<Integer>) |
| Speed | Slightly faster, less overhead | A little slower, but rarely the bottleneck |
| API | Tiny (.length, indexing) | Rich (add, remove, contains, sort, …) |
| When to use | Performance-critical numeric code, or when size is truly fixed | Almost everywhere else |
In modern Java code, you'll see ArrayList (or List) far
more often than bare arrays.
What happens if you try scores[scores.length] on a Java array?
Returns 0
Returns null
Throws ArrayIndexOutOfBoundsException at runtime
Grows the array by one
Why is List<Integer> used instead of int[] in most everyday code?
It is faster
It can grow and shrink, has a richer API, and integrates with the rest of the collections framework
It uses less memory
The compiler refuses to use int[]
What is wrong with removing an element from a list inside a for-each loop over that same list?
The compiler refuses to compile it
Nothing — that's the recommended pattern
It throws ConcurrentModificationException because the iterator detects the structural change
It silently loses one element
A challenge
Implement a static method Numbers.sumPositive(List<Integer>) that returns the sum of the positive numbers in the list (numbers strictly greater than zero). Zeros and negatives are ignored.
Main.java is given. It must print exactly:
sumPositive=15
Lists are great for ordered sequences. But many problems need to
ask "is this thing here?" or "what value goes with this key?"
quickly. That's the job of Set and Map, which we tackle next.