CSCD 211 › lessons

Week 2: ArrayList and the List interface, built from "what holds a list you cannot size in advance?"

By the end you can hold a collection that grows as you add to it, declare it by the interface it satisfies rather than the class that implements it, and read the angle-bracket type that keeps the collection honest about what it holds. This is the list your Schedule field has been already, named and understood.

The user story behind this. A department chair wants to add courses to a term's schedule one at a time and not have to know the final count in advance, so that building a schedule feels like making a list, not sizing an array before they have decided what is on it. The collection has to grow on demand.

Before you start

The problem (sit with this before reading on)

You want a schedule to hold courses, but you do not know how many until the chair is done adding them. An array makes you commit up front:

Course[] courses = new Course[5];   // why 5? what about the sixth?

Pick too small and the sixth course has nowhere to go; pick too big and you carry empty slots and a separate count of how many are real. The size is a decision you are forced to make before you have the information to make it.

Check yourself. In one sentence, what is the specific problem with new Course[5] when you do not yet know how many courses there will be?

Atom 1: an ArrayList grows on demand

An ArrayList is a list that resizes itself as you add to it. You never set its size; you just add:

List<Course> courses = new ArrayList<>();
courses.add(intro);
courses.add(systems);
int howMany = courses.size();   // 2, and it grows as you add more

There is no capacity to guess. add makes room, size tells you how many are really there, and get(i) reads the one at a position. The list holds exactly what you put in it and no empty slots.

Check yourself. After courses.add(intro); courses.add(systems);, what does courses.size() return, and did you have to decide a size anywhere?

Atom 2: declare it by the interface, build it with the class

Look again at the declaration: the variable type is List, but the object is an ArrayList. That is on purpose. List is an interface, a promise of what a list can do (add, get, size, iterate); ArrayList is one class that keeps that promise, using an array inside that it grows for you. You write the field as List<Course> so the rest of your code depends only on the promise, not on the particular implementation.

The payoff is that the implementation can change without the rest of your code noticing. Swap new ArrayList<>() for another List and every method that took a List still works, because it only ever used the promise. You met this idea in Week 1: Comparable was an interface, a promise of a method. List is a bigger promise, kept by ArrayList.

Check yourself. The field is List<Course> but the object is new ArrayList<>(). In one sentence, what does writing the type as the interface buy you?

Atom 3: the angle brackets keep the list honest

The List<Course> says this is a list of Course and nothing else. The compiler holds you to it: you cannot add a String to a List<Course>, and when you read an element back you get a Course with no cast. That angle-bracket type is generics, and the empty pair on the right, new ArrayList<>(), is the diamond, which says build an ArrayList of the same type the left side already named.

You will see generics in depth later, when you build a structure that is generic over its element type. For now the one idea you need is that the angle brackets say what is inside, and the compiler enforces it, so a list of courses cannot quietly end up holding something else.

Check yourself. You have List<Course> courses. In one sentence, what does the compiler do if you write courses.add("CSCD 211"), and why?

Atom 4: read it with an enhanced-for

Because a List knows how to be iterated, the enhanced-for reads it cleanly, the same loop your Schedule already uses to total credits:

for (Course c : courses) {
    System.out.println(c.title());
}

No index, no size, no get(i). The loop asks the list for each element in turn. This is the everyday way to read a collection, and it is the loop a custom list you build later will have to support to feel like a real list.

Check yourself (competency close). Finish in your own words: "An ArrayList solves the array problem because . I declare the field as List rather than ArrayList so that , and the <Course> means ___."

What you collected

Where this is going

You can now hold one fixed value safely (enums) and many values that grow (ArrayList), and you can compose and protect them (composition and defensive copy). That is the whole Week 2 toolkit for building the catalog and the schedule. Week 3 starts building a list of your own, from a single node up, so you understand from the inside what ArrayList has been doing for you.