W3docs

Java Collections Framework Overview

A high-level tour of the Java Collections Framework — interfaces, implementations, and algorithms in java.util.

Java Collections Framework Overview

Almost every program ends up holding a group of things — orders waiting to ship, words in a document, users currently online, the line of pending tasks a worker thread will pick up next. Java's answer to "where do I put that group" is the Collections Framework: a coordinated set of interfaces in java.util, a dozen-plus implementations behind them, and a single utility class of algorithms (Collections) that works against the interfaces rather than any specific implementation. This chapter is the map — what's in the framework, why it's shaped the way it is, and which family you reach for in which situation. Every chapter in this part is a deep-dive into one of the boxes on that map.

Why a framework, not just classes

Before Java 1.2 there were classes for groups (Vector, Hashtable, Stack) but no shared interface — you couldn't write a method that took "any list" and have it accept all three. The Collections Framework fixed that by separating what a group is (the interface) from how it's stored (the implementation). The payoff is on display every day:

// You program against the interface, not the class.
List<String> names = new ArrayList<>();
// Later, swap in a different implementation without touching the rest of the code:
List<String> names = new LinkedList<>();

Every method you call on names is defined on List. The choice of ArrayList vs. LinkedList is a performance decision, not an API decision. You can also write methods like void print(List<String> xs) once and pass either implementation in.

The four root interfaces

The framework is organised around four root interfaces. Pick the one whose contract matches what your data is:

  • Collection<E> — the root. A group of E elements. Nothing said about order, duplicates, or indexing.
  • List<E> — an ordered collection accessible by index. Duplicates allowed. Think "array that grows" or "linked sequence." ArrayList, LinkedList, Vector.
  • Set<E> — a collection that forbids duplicates. Mathematical set. May or may not be ordered. HashSet, LinkedHashSet, TreeSet.
  • Map<K, V> — key→value lookup. Not a Collection (its elements are entries, not single values), but lives in the framework. HashMap, LinkedHashMap, TreeMap.

Two more sit alongside List and Set as specialisations of Collection:

  • Queue<E> — a "next in line" collection. FIFO by default. LinkedList, ArrayDeque, PriorityQueue.
  • Deque<E> — a double-ended queue. Add and remove at either end. ArrayDeque, LinkedList.

Every collection class in the standard library implements at least one of these.

Pick the family by behaviour, then the class by cost

The decision is two layers:

  1. What does the data need? Ordered with duplicates → List. No duplicates → Set. Lookup by key → Map. Producer/consumer → Queue or Deque.
  2. Inside the family, what are the access patterns? Random access by index → ArrayList. Heavy add/remove at the front → LinkedList or ArrayDeque. Sorted iteration → TreeSet / TreeMap. Plain "I just need a fast bag" → HashSet / HashMap.

A rough cheat sheet for the workhorses:

NeedUseNotes
Resizable list, fast random accessArrayListThe default List.
List with very frequent insert/remove at endsArrayDeque (as a list-like queue)Beats LinkedList in practice.
Set, fast contains/add/removeHashSetNo order guarantee.
Set with predictable iterationLinkedHashSetInsertion-order iteration.
Sorted setTreeSetO(log n) operations.
Map, fast lookupHashMapThe default Map.
Map with predictable iterationLinkedHashMapUseful for caches (LRU).
Sorted mapTreeMapKeys in sorted order.
FIFO queueArrayDequeFaster than LinkedList.
Always-poll-the-smallestPriorityQueueHeap-backed.

Vector, Stack, and Hashtable are the pre-1.2 classes — still in the JDK for backward compatibility, but no longer the right choice in new code. Their modern replacements are covered in their own chapters.

Generics make collections type-safe

Every collection interface and class is generic. You parameterise it with the element type at the declaration site, and the compiler enforces it from then on:

List<String> names = new ArrayList<>();
names.add("Ada");
names.add(42);          // ❌ compile error — Integer is not a String
String first = names.get(0);   // no cast needed

The diamond <> on the right asks the compiler to infer the type from the left — it saves typing without losing the safety. The previous part of the book (Generics) is the rulebook behind all of this; the rest of this part assumes you read it.

Algorithms live on the Collections class

Operations that aren't tied to a specific implementation — sort, shuffle, reverse, binary-search, min, max, frequency, unmodifiable wrappers — live on the static utility class java.util.Collections. Note the s at the end: Collection (the interface) is one element; Collections (the class) is the toolkit:

List<Integer> xs = new ArrayList<>(List.of(3, 1, 4, 1, 5, 9, 2, 6));
Collections.sort(xs);                    // mutates xs
int idx = Collections.binarySearch(xs, 5);
List<Integer> ro = Collections.unmodifiableList(xs);

We dedicate three chapters near the end of this part to Collections — searching, sorting, and unmodifiable wrappers — because the utility class is where a lot of practical work happens.

A first complete tour

The program below picks one representative from each family and shows the operations you'll be using over and over. Don't worry about understanding every line yet — every class here gets its own chapter. The goal is to see the shape of the framework: same method names, same patterns, same iteration model.

java— editable, runs on the server

Notice three things in the output:

  1. The Set quietly dropped the duplicate "Effective Java". That's the contract — no extra code needed on your side.
  2. The Queue returned items in the order they were added. offer enqueues, peek looks at the head without removing, poll removes and returns it.
  3. The for-each loop works on every Collection. Maps iterate via entrySet(), keySet(), or values() depending on what you want.

That's the framework in miniature.

What's next

You've seen the map. The rest of Part 11 walks each region. The natural starting point is the root every collection inherits from — the Collection interface itself, where methods like add, remove, contains, size, and iterator() are defined once and for all.

Practice

Practice

You need to store a group of words and quickly answer 'is this word in the group?' Duplicates are not interesting — `cat` either appears or doesn't. Which family of the Collections Framework is the natural fit?