What you'll learn
Arrays are fixed-size and low-level. The Java Collections Framework gives you flexible, powerful data structures — resizable lists, unique sets, key-value maps — that you'll use in almost every program you write.
By the end you'll be able to:
- Navigate the collection hierarchy:
List,Set,Queue,Map - Use
ArrayList,HashSet, andHashMapconfidently - Iterate collections and sort them with
ComparableandComparator - Pick the right collection for the job — and know why
The collection hierarchy
Everything (except maps) descends from Iterable and Collection, which define shared operations like add, remove, size, and contains.Map sits apart because it stores key-value pairs, not single elements:
Iterable → Collection
├ List — ordered, duplicates OK
│ ArrayList, LinkedList
├ Set — no duplicates
│ HashSet, LinkedHashSet, TreeSet
└ Queue/Deque — ends
ArrayDeque, PriorityQueue
Map (separate — key → value)
HashMap — fast, unordered
LinkedHashMap — insertion order
TreeMap — sorted by key
Tip
List<String> x = new ArrayList<>(), not ArrayList<String> x = .... It keeps your code flexible if you swap implementations later.List
A List is an ordered collection that allows duplicates and gives you access by index — think of it as a resizable array. ArrayList is the go-to implementation:
import java.util.*;
List<String> fruits = new ArrayList<>();
fruits.add("apple");
fruits.add("banana");
fruits.add("cherry");
fruits.remove("banana");
System.out.println(fruits); // [apple, cherry]
System.out.println(fruits.get(0)); // apple
System.out.println(fruits.size()); // 2
System.out.println(fruits.contains("cherry")); // true| Implementation | Best at | Weak at |
|---|---|---|
ArrayList | Fast random access by index; the default choice | Inserting/removing in the middle |
LinkedList | Fast add/remove at the ends (queue/deque) | Random access by index |
Set
A Set holds unique elements — adding a duplicate does nothing. Reach for a set whenever "no repeats" matters (unique visitors, tags, IDs):
import java.util.*;
Set<Integer> nums = new HashSet<>();
nums.add(1);
nums.add(2);
nums.add(2); // duplicate — silently ignored
nums.add(3);
System.out.println(nums.size()); // 3
Set<String> sorted = new TreeSet<>(List.of("banana", "apple", "cherry"));
System.out.println(sorted); // sorted automatically| Implementation | Order | Notes |
|---|---|---|
HashSet | None | Fastest; the default set |
LinkedHashSet | Insertion order | Remembers the order you added items |
TreeSet | Sorted | Keeps elements in sorted order automatically |
Queue & Deque
A Queue processes elements in order — usually FIFO (first-in, first-out). A Deque ("double-ended queue") lets you add and remove from both ends, so it can act as a stack too. ArrayDeque is the efficient default; PriorityQueue always serves the "smallest" element first.
Note
ArrayDeque (push/pop) rather than the legacy Stack class. Need "always the highest priority next"? Use PriorityQueue.Map
A Map stores key → value pairs with fast lookup by key — like a dictionary. Each key is unique; putting a value under an existing key overwrites it. This is one of the most useful structures in all of programming:
import java.util.*;
Map<String, Integer> ages = new HashMap<>();
ages.put("Sara", 25);
ages.put("Omar", 30);
ages.put("Sara", 26); // same key overwrites
System.out.println(ages.get("Sara")); // 26
System.out.println(ages.getOrDefault("X", 0)); // 0
System.out.println(ages.containsKey("Omar")); // true
for (var entry : ages.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}| Implementation | Order | Notes |
|---|---|---|
HashMap | None | Fastest; the default map |
LinkedHashMap | Insertion order | Predictable iteration order |
TreeMap | Sorted by key | Keys kept in sorted order |
Comparable & Comparator
To sort objects, Java needs to know how to order them. Comparable defines a type's natural order (implement compareTo once inside the class). Comparator is a separate, reusable ordering you can pass in — perfect for sorting by different fields on demand:
import java.util.*;
List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
Collections.sort(names); // natural (alphabetical) order
System.out.println(names);
names.sort(Comparator.comparingInt(String::length)); // custom: by length
System.out.println(names);Tip
Comparator has fluent builders: Comparator.comparing(...), .thenComparing(...), and .reversed() chain together to express complex sort orders in one readable line.Choosing the right collection
Let your requirement guide the choice:
| If you need… | Use |
|---|---|
| An ordered list with duplicates, indexed access | ArrayList |
| Unique elements, fastest | HashSet |
| Unique elements, kept sorted | TreeSet |
| Key → value lookup, fastest | HashMap |
| Key → value, sorted by key | TreeMap |
| A queue or stack | ArrayDeque |
| Always retrieve the smallest/highest-priority next | PriorityQueue |
A word on performance
ArrayList is O(1). You'll go deep on this in Module 35.Recap & quick check
Key takeaways
- List = ordered with duplicates (ArrayList); Set = unique (HashSet); Map = key→value (HashMap).
- Program to the interface (List/Set/Map), not the concrete class.
- TreeSet/TreeMap stay sorted; LinkedHashSet/LinkedHashMap keep insertion order.
- Comparable defines a natural order; Comparator defines custom, reusable orderings.
- Match the collection to the requirement: uniqueness, ordering, lookup speed, or index access.
Quick check
1. Which collection prevents duplicate elements?
2. What does a Map store?
3. Which List implementation is best for fast access by index?
4. How do you give a class its own natural sort order?
5. Which map keeps its keys sorted?
Excellent — collections are the workhorses of everyday Java. Next up: Module 15 — the Object class & essential APIs.