Collections Framework I
Fundamentals closes with the tool used constantly in real Java code: growable, generic collections — starting with List, the interface Course 2's own Collections Framework II picks up from with Map/Set/Queue.
ArrayList — A Growable Array
A plain Java array's size is fixed the moment it's created. ArrayList is backed internally by an array too, but resizes itself automatically as elements are added — the size a caller actually deals with is never fixed at all.
Generics in Collections
List<String> tells the compiler exactly what type this list holds, catching a type mismatch at compile time rather than at some later runtime cast. Before generics existed, Java collections held plain Object references, requiring an explicit, unchecked cast on every read — a real source of runtime ClassCastExceptions generics eliminate outright. Course 2's own Generics In Depth chapter goes further into how generics work themselves; this chapter only needs the collection-facing side.
Programming to the Interface
The variable is declared as List<String>, not ArrayList<String>, even though an ArrayList is what's actually constructed. This mirrors java1-6's own interface-vs-implementation split directly: code written against the List interface keeps working unchanged if the concrete implementation is later swapped for a LinkedList or any other List.
Iterating — for-each, Iterator, and Safe Removal
The for-each form is the everyday choice for read-only iteration. Removing an element while iterating requires the explicit Iterator and its own remove() — removing directly from the list during a for-each is not safe, covered next.
Java's Own Answer to the STL Containers
ArrayList is directly comparable to cpp2-2's own std::vector — both are growable, contiguous, general-purpose sequence containers. The real difference traces straight back to java1-2's boxing material: a C++ std::vector<int> stores raw int values directly, no wrapping required, since C++ templates generate real code specialized for the exact type. Java generics can't hold a primitive int at all — List<int> doesn't compile — so List<Integer> is required instead, and every element is autoboxed on the way in.
| Behavior | C++ std::vector (cpp2-2) | Java ArrayList |
|---|---|---|
| Growable | yes | yes |
| Holding a primitive/raw int | yes — stored directly, no wrapping | no — must box to Integer (java1-2) |
| Declared-type convention | the concrete container type itself | the interface (List), not ArrayList |
List<String> list = new ArrayList<>(); — this single habit keeps calling code decoupled from exactly which List implementation is in use, the same interface-over-implementation instinct from java1-6.
list.remove(...) directly on the list while a for-each loop is iterating over it throws ConcurrentModificationException — the for-each's hidden iterator detects the list changed underneath it. Use Iterator.remove() instead, the only safe way to remove elements mid-iteration.
Coding Challenges
Create a List<Integer> declared using the List interface, add five numbers to it via an ArrayList, then print them using a for-each loop and explain in a comment where autoboxing happens.
📄 View solutionWrite code that removes every element equal to a target value from a List<String> directly during a for-each loop, showing the resulting ConcurrentModificationException, then fix it correctly using an explicit Iterator's remove() method.
📄 View solutionExplain why List<int> does not compile in Java, but List<Integer> does, tying your answer back to java1-2's own primitives-vs-reference-types material and to how C++'s std::vector<int> differs.
📄 View solutionChapter 8 Quick Reference — Course 1 Complete
- ArrayList resizes automatically, unlike a plain Java array's fixed size
- Generics catch type mismatches at compile time, replacing the pre-generics Object-cast pattern
- Declare with the interface (List), construct with the implementation (ArrayList) — mirrors java1-6's interface-vs-implementation split
- Removing during a for-each throws ConcurrentModificationException — use Iterator.remove() instead
- ArrayList is Java's answer to cpp2-2's std::vector, but genuinely can't hold primitives directly — everything boxes, per java1-2
- Java Fundamentals is now complete. Course 2 (Intermediate/Advanced) begins with Generics In Depth — Java's type-erasure strategy, contrasted directly against C++ and Rust's shared monomorphization approach.