The Collections Framework
Why Java 1.2 introduced a unified hierarchy of interfaces and implementations — and the shape of the framework you'll use for the rest of the course
In December 1998, Java 1.2 shipped a redesign of java.util that
changed how everyone wrote Java. It was called the Java Collections
Framework (JCF), and it was the answer to every complaint about
Vector and Hashtable.
The framework was deliberately designed by a single architect, Josh Bloch, with a specific goal: a small set of interfaces that describe what a container is, and a small set of high-quality implementations of each. The combination of those two ideas is what makes the JCF feel coherent even today, almost three decades later.
The two big ideas
That is it. From those four goals everything else follows: the
interface hierarchy, the Collections static-utility class, the
Iterator interface, the standard implementations, and the way
methods all over the JDK are declared in terms of List, Set,
Map instead of concrete types.
The interface hierarchy
Here is the shape of the framework. Memorize this diagram — every remaining page in the course refers to some corner of it.
Map is not a subtype of Collection — it is its own hierarchy:
The reason Map is separate is that a map is fundamentally about
pairs (key, value), not about elements. We'll dwell on that in
the Maps chapter.
What each interface means
The vocabulary of the JCF is small and worth saying out loud:
| Interface | Meaning | Mental model |
|---|---|---|
Iterable<E> | "I can be walked from start to finish" | A row of things |
Collection<E> | "I am a group of elements" | A bag |
List<E> | "I am an ordered, indexed sequence" | A row with seat numbers |
Set<E> | "I am a group with no duplicates" | A set of unique stickers |
SortedSet<E> | "I am a set whose iteration order is sorted" | A library shelf |
Queue<E> | "I am a group with a head, things enter at one end" | A line at a coffee shop |
Deque<E> | "I am a queue with two ends" | A deck of cards you can draw from either end |
Map<K,V> | "I am a function from keys to values" | A phone book |
SortedMap<K,V> | "...whose keys iterate in sorted order" | A dictionary |
You will reach for the names on the left in your method signatures. The implementations come next.
The default implementations
For each interface, the JCF ships one (sometimes two) production-grade implementation. This is the table you will internalize over the course:
| Interface | Default implementation | Backed by |
|---|---|---|
List<E> | ArrayList<E> | A growing Object[] |
List<E> (linked) | LinkedList<E> | A doubly-linked node chain |
Set<E> | HashSet<E> | A HashMap |
Set<E> (insertion-ordered) | LinkedHashSet<E> | A hash table + linked list |
SortedSet<E> | TreeSet<E> | A red-black tree |
Queue<E> | ArrayDeque<E> or PriorityQueue<E> | Circular array / binary heap |
Deque<E> | ArrayDeque<E> | Circular array |
Map<K,V> | HashMap<K,V> | A hash table |
Map<K,V> (insertion-ordered) | LinkedHashMap<K,V> | Hash table + linked list |
SortedMap<K,V> | TreeMap<K,V> | A red-black tree |
Each implementation has its own performance and memory profile. We will earn that table over many pages — for now, it's a road map.
Programming to the interface
The single most important rule the JCF teaches you:
Declare variables and parameters with the interface type; pick the implementation only at construction.
If totalLength had been declared totalLength(ArrayList<String>),
callers with a LinkedList would have been stuck. By accepting
List<String>, the method gains every present and future List
implementation for free.
The Collections utility class
A second hallmark of the framework is that algorithms live
separately from data structures. The class java.util.Collections
holds static helpers — sort, shuffle, reverse,
unmodifiableList, frequency, min, max — that work on any
matching collection.
Notice you did not write a sort. You did not write a min. You did not
write a frequency-counter. They work on ArrayList, on LinkedList,
on user-written List implementations — anything that says "I am a
List."
Iterator: a real walking protocol
The JCF replaced Enumeration with Iterator, which adds one
crucial method: remove(). It also became the basis of the
for-each loop in Java 5.
That it.remove() is what Enumeration could never do safely. We
will return to iterators in their own chapter.
A first multi-file example: programming to interfaces
This shows the JCF style end-to-end. A Library consumes a
List<Book> and a Set<String> — it does not care which
implementation you hand it.
Library would work just as well if books were a LinkedList and
bannedAuthors were a TreeSet. That is the whole point.
Practice
Write a class Roster that holds a List<String> of student names and exposes:
void addStudent(String name)— appends the nameint size()— the number of studentsboolean has(String name)— whether the roster contains that nameList<String> all()— the underlying list
The constructor must take a List<String> as its only argument, so callers can pass any implementation they like (ArrayList, LinkedList, ...). The provided Main will exercise it. Expected output:
size = 3
has Ada? true
has Bob? false
Ada
Grace
Linus
Test your understanding
What was the primary design idea introduced by the Java Collections Framework?
Faster sorting algorithms
Separating interfaces that describe container shapes from implementations that realize them
Replacing arrays as the JVM's underlying storage
Adding network synchronization to data structures
Why is Map not a subtype of Collection?
Because maps don't store data
Because maps fundamentally hold (key, value) pairs, not single elements, so the Collection operations (add(E), contains(E)) don't fit
Because Map is older than Collection
Because maps cannot be iterated
Why is it a good habit to write List<String> names = new ArrayList<>(); rather than ArrayList<String> names = new ArrayList<>();?
It compiles faster
The variable is typed by what it represents (a list of strings), so the implementation can be swapped without touching the rest of the code
ArrayList does not exist in modern Java
The garbage collector treats interfaces and classes differently
The Birth of Reusable Containers
From hand-rolled arrays to Java 1.0's first container classes — Vector, Stack, Hashtable, Enumeration — and the lessons learned
The Generics Revolution
How Java 5 generics solved the type-safety problem the Collections Framework was missing, and what the world looked like before and after