Java Collections Framework
The Java Collections Framework is Java's toolbox for storing groups of objects: lists, sets,
queues, and maps. Instead of building your own data structures, you pick a tested one like
ArrayList or HashMap. This guide walks through the collection hierarchy, what each
interface is for, and how to choose the right one.
What is the Collections Framework?
It's a set of interfaces (what a collection can do) and classes (how it does
it) in the java.util package. Think of a kitchen: you have a cutlery tray (ordered slots), a spice
rack (one of each), and labelled jars (look up by name). Each container suits a different job.
Why not just use arrays?
Arrays have a fixed size. Once you create new String[10], you can't add an 11th item. Collections
grow and shrink automatically and come with handy methods like contains(), remove(),
and sorting.
The Java collection hierarchy
Everything is built on interfaces, so your code can depend on a
type of collection (like List) rather than a specific class (like ArrayList):
Collection hierarchy (main types)
- Iterable interface: anything you can loop over with for-each
- Collection interface: a group of elements
- List ordered, duplicates OK
- ArrayList, LinkedList classes
- Set no duplicates
- HashSet, LinkedHashSet classes
- SortedSet → NavigableSet → TreeSet kept sorted
- Queue process in order
- PriorityQueue class
- Deque → ArrayDeque, LinkedList both ends
- List ordered, duplicates OK
- Collection interface: a group of elements
- Map interface: key → value pairs (separate hierarchy)
- HashMap, LinkedHashMap classes
- SortedMap → NavigableMap → TreeMap sorted by key
Interfaces sit above, implementations below. Map is part of the framework but not a
Collection, because it stores pairs, not single elements. Since Java 21, SequencedCollection
and SequencedMap also sit in this tree for types with a defined order, adding methods like getFirst() and reversed().
The core collection interfaces
| Interface | Order | Duplicates | Main use | Go-to class |
|---|---|---|---|---|
List | Insertion order, indexed | ✔ Allowed | A sequence of items | ArrayList |
Set | None (depends on class) | ✘ Not allowed | Unique items, fast "contains?" | HashSet |
Queue / Deque | Processing order | ✔ Allowed | Waiting lines, stacks | ArrayDeque |
Map | None (depends on class) | Keys unique | Look up a value by key | HashMap |
Which collection should I use?
Start from what you need, not from the class names. Pick a need below:
Pick what you need
Ordered, duplicates OK
Use a List, normally ArrayList.
- Keeps insertion order
- Allows duplicates
- Fast access by index:
list.get(3) - Example: items in a shopping cart
List<String> cart = new ArrayList<>();
cart.add("Milk");
cart.add("Milk"); // duplicates allowed Unique items only
Use a Set, normally HashSet. Use LinkedHashSet to keep insertion order or TreeSet to keep it sorted.
- No duplicates
- Very fast
contains()checks - Example: unique visitor IDs
Set<String> tags = new HashSet<>();
tags.add("java");
tags.add("java"); // ignored, already present Look up by key
Use a Map, normally HashMap. Use LinkedHashMap for insertion order or TreeMap for sorted keys.
- Stores key → value pairs
- Keys are unique
- Example: username → user profile
Map<String, Integer> stock = new HashMap<>();
stock.put("apples", 12);
stock.get("apples"); // 12 Process in order
Use a Queue/Deque, normally ArrayDeque, or PriorityQueue to process the smallest or most urgent item first.
- First in, first out (FIFO), or last in, first out as a stack
- Example: print jobs, undo history
Deque<String> jobs = new ArrayDeque<>();
jobs.offer("print A");
jobs.offer("print B");
jobs.poll(); // "print A" Comparing the main implementations
| Class | Keeps order? | Lookup / contains | Good to know |
|---|---|---|---|
ArrayList | Insertion | By index: fast · by value: slower | Best default list |
LinkedList | Insertion | Slower | Rarely the best choice; ArrayDeque is usually faster as a queue |
HashSet / HashMap | No | Fast | Elements need proper equals() and hashCode() |
LinkedHashSet / LinkedHashMap | Insertion | Fast | Slightly more memory than Hash versions |
TreeSet / TreeMap | Sorted | Medium (logarithmic) | Supports ranges like "everything after X" |
ArrayDeque | Both ends | Fast at ends | Best queue and stack |
PriorityQueue | By priority | Fast to peek at smallest | Iteration order isn't sorted, only removal order |
Let's see it in action
Here's one small program using a List, a Set, and a Map together, counting words in a sentence:
import java.util.*;
public class WordStats {
public static void main(String[] args) {
List<String> words = List.of("the", "cat", "sat", "on", "the", "mat");
Set<String> unique = new TreeSet<>(words); // removes duplicates, keeps sorted
Map<String, Integer> counts = new TreeMap<>();
for (String w : words) {
counts.merge(w, 1, Integer::sum); // add 1 to this word's count
}
System.out.println("All words: " + words);
System.out.println("Unique words: " + unique);
System.out.println("Counts: " + counts);
}
} All words: [the, cat, sat, on, the, mat]
Unique words: [cat, mat, on, sat, the]
Counts: {cat=1, mat=1, on=1, sat=1, the=2} List.of(...)— a quick, unmodifiable list.new TreeSet<>(words)— copies the words into a sorted set, so the duplicate "the" disappears.counts.merge(w, 1, Integer::sum)— "put 1 if the word is new, otherwise add 1 to what's there".
Tip: declare variables with the interface type
List<String> names = new ArrayList<>(); // ✔ preferred
ArrayList<String> names2 = new ArrayList<>(); // works, but ties your code to one class
If you later need a different list implementation, you change one word, and the rest of the code keeps working.
The <String> part is a generic type; it tells Java the collection holds
Strings, so the compiler stops you from adding anything else.
Helpful utilities: Collections and factory methods
List.of(...),Set.of(...),Map.of(...)— create small unmodifiable collections in one line (Java 9+).Collections.sort(list),Collections.reverse(list),Collections.max(c)— static helpers in theCollectionsutility class. Note the plural "s".Collections.unmodifiableList(list)— a read-only view of an existing list.
Thread safety: ArrayList, HashMap, and the other standard classes are not safe to modify from several threads at once. See thread-safe lists in Java for the options.
Quick recap
- The Collections Framework is a set of interfaces and classes in
java.util. List= ordered with duplicates,Set= unique,Queue= processing order,Map= key → value.Mapis part of the framework but doesn't extendCollection.- Defaults:
ArrayList,HashSet,HashMap,ArrayDeque. - Declare variables using the interface type:
List<String> x = new ArrayList<>().
What's next?
Get hands-on with the most-used collection in Java ArrayList (and how to sort it), then learn to share lists safely between threads in thread-safe lists.
Frequently Asked Questions
What is the Java Collections Framework?
It's the set of ready-made interfaces and classes in java.util for storing and working with groups of objects: lists, sets, queues, and maps. It gives you tested data structures like ArrayList and HashMap so you don't have to build your own.
Is Map part of the Collection hierarchy?
Map is part of the Collections Framework, but it does not extend the Collection interface. A Map stores key-value pairs rather than single elements, so it has its own hierarchy. You can still view a map's keys, values, or entries as collections.
What is the difference between List and Set in Java?
A List keeps elements in order and allows duplicates, and you can access items by position. A Set doesn't allow duplicates: adding an element that's already there has no effect. Use a Set when uniqueness matters, such as a set of email addresses.
What is the difference between Collection and Collections?
Collection (singular) is the root interface that List, Set, and Queue extend. Collections (plural) is a utility class full of static helper methods such as Collections.sort(), Collections.reverse(), and Collections.unmodifiableList().
Which collection should I use by default?
For most code: ArrayList when you need a list, HashSet for unique items, HashMap for key-value lookups, and ArrayDeque for a queue or stack. Switch to a specialised implementation only when you need sorting, insertion order, or thread safety.