ArrayList and its Methods

Why ArrayList Exists

An array's size is fixed forever once created. ArrayList is Java's resizable alternative — use it whenever you don't know the final size up front, or items will be added/removed while the program runs (a growing log of events, for instance).

import java.util.ArrayList;

// <> ("the diamond") repeats the left side's type
ArrayList<String> logs = new ArrayList<>();
logs.add("Robot Initialized");

The <> on the right doesn't need to spell out String again — Java infers it from the declared type on the left. new ArrayList<String>() still works too; the diamond form is what you'll see in real code.

The Type Parameter

ArrayList<Type> — the type in angle brackets is what kind of object the list holds. ArrayList can only hold objects, never primitives directly — a list of numbers uses a wrapper type like Integer/Double (Java auto-converts back and forth, called autoboxing/unboxing):

ArrayList<Double> sensorReadings = new ArrayList<>();
sensorReadings.add(2.4); // autoboxed into a Double automatically

Wrapper Classes

Every primitive type has a matching wrapper class — an object version of that value, which is what makes it usable inside an ArrayList:

PrimitiveWrapper
intInteger
doubleDouble
booleanBoolean
charCharacter
double first = sensorReadings.get(0); // unboxed back into a double automatically

Java converts back and forth automatically — autoboxing (primitive → wrapper) and unboxing (wrapper → primitive). Three things worth knowing before they bite:

  • Unboxing a null throws NullPointerException. A wrapper variable (or an ArrayList<Integer> slot) can hold null; the instant Java tries to unbox it into a primitive, it crashes — this is exactly what a "missing key" bug in Lesson 9.3 looks like.
  • == on Integer is unreliable. Like any object, == checks identity, not value — except Java happens to cache small Integer values (-128 to 127), so == can look like it "works" for small numbers and silently fail for larger ones. Use .equals() for wrapper objects, same as any other object.
  • Turning text into a number needs parseInt/parseDouble, not autoboxing. Integer.parseInt("42") and Double.parseDouble("3.14") convert text (e.g. a field split from a CSV line, Ch.9.8) into a primitive — a separate conversion from autoboxing, which only ever converts between a primitive and its own wrapper.

Core Methods

ArrayList<String> logs = new ArrayList<>();
logs.size();             // number of elements (like length, but a method — () required)
logs.add("started");     // appends to the end
logs.add(0, "boot");     // inserts at index 0, shifting everything else right
logs.get(0);              // reads the element at index 0
logs.set(0, "ready");     // replaces the element at index 0
logs.remove(0);           // removes BY INDEX — the element at index 0
logs.remove("ready");     // removes BY VALUE — the first element .equals("ready")
logs.contains("ready");   // true if any element .equals("ready")
logs.indexOf("ready");    // index of the first match, or -1 if not present
logs.isEmpty();           // true if size() == 0

ArrayList uses methods (get/set) instead of [] — it's a real class, not a built-in language feature the way arrays are.

Array vs. ArrayList, Side by Side

OperationarrayArrayList
countarr.lengthlist.size()
readarr[i]list.get(i)
writearr[i] = v;list.set(i, v);
grow/shrinknot possibleadd/remove

Common Pitfalls

  • Using [] on an ArrayList. It doesn't compile — always get(i)/set(i, v) instead.
  • Mixing up .length and .size(). Arrays use the field .length; ArrayList uses the method .size().
  • Using an uninitialized ArrayList. Declaring ArrayList<String> list; without new ArrayList<>() leaves it null — calling any method on it throws NullPointerException.
  • remove(30) on an ArrayList<Integer> doesn't remove the value 30. An int argument always picks the remove(int index) overload — it removes by position. To remove the value, wrap it: remove(Integer.valueOf(30)) (or remove((Integer) 30)).

Key Takeaways

  • ArrayList is a resizable list — use it when the size isn't known up front or will change at runtime.
  • The type parameter (ArrayList<Type>) says what it holds; primitives need their wrapper type (Integer, Double, Boolean, Character) — autoboxing/unboxing converts automatically, but unboxing a null throws NullPointerException, and == on wrappers is unreliable (use .equals()).
  • The diamond (new ArrayList<>()) infers the type parameter from the declared type on the left.
  • Core methods: size(), add(), add(index, obj), get(index), set(index, obj), remove(index), remove(Object), contains(), indexOf(), isEmpty().
  • Arrays use .length and []; ArrayList uses .size() and get/set.

Derived from csawesome-2026: unit-4-data-collections/4.08-arraylist-and-its-methods.md (CSA 4.8)