Core Interfaces
List, Set, Map, Queue and Deque interfaces
Collections Framework â Core Interfaces
The Java Collections Framework defines a hierarchy of interfaces â List, Set, Map, Queue, Deque â each representing a distinct contract for storing and accessing data.
1. Definition
What is it?
The Java Collections Framework (JCF) is a unified architecture for representing and manipulating groups of objects. At its core are a set of interfaces that define the contracts â the what, not the how â of different collection types.
Why does it exist?
Before JCF (pre-Java 1.2), Java had only Vector, Stack, Hashtable, and arrays â each with inconsistent APIs. JCF introduced a coherent hierarchy so that:
- Algorithms can be written against interfaces, not concrete classes
- Implementations are interchangeable without breaking callers
- Common operations (iteration, sorting, filtering) work uniformly
Where does it fit?
Main interface hierarchy summary:
Iterablesits at the top.CollectionextendsIterable.Listis the ordered branch and allows duplicates.Setis the no-duplicates branch, withSortedSetandNavigableSetvariants.Queuecovers FIFO or priority-oriented access, withDequeas the double-ended variant.Mapis a separate key-value hierarchy, withSortedMapandNavigableMapas ordered variants.
2. Core Concepts
2.1 `Collection` â the root interface
The root of the collection hierarchy (excluding Map). Provides:
add(E e),remove(Object o),contains(Object o)size(),isEmpty(),clear()iterator(),forEach(),stream()- Bulk operations:
addAll,removeAll,retainAll,containsAll
2.2 `List` â ordered, index-accessible
| Property | Details |
|---|---|
| Order | Insertion order preserved |
| Duplicates | â Allowed |
| Index access | â
get(int index) |
| Null elements | â Usually allowed |
| Key implementations | ArrayList, LinkedList, CopyOnWriteArrayList |
Key additional methods: get(int), set(int, E), add(int, E), remove(int), indexOf(Object), subList(from, to), sort(Comparator).
2.3 `Set` â no duplicates
| Property | Details |
|---|---|
| Order | Depends on implementation (none/insertion/sorted) |
| Duplicates | â Not allowed (determined by equals/hashCode) |
| Index access | â No get(int) |
| Null elements | â At most one null |
| Key implementations | HashSet, LinkedHashSet, TreeSet |
SortedSet adds: first(), last(), headSet(to), tailSet(from), subSet(from, to).
NavigableSet adds: floor(e), ceiling(e), lower(e), higher(e), descendingSet().
2.4 `Queue` â FIFO access
| Operation | Throws exception | Returns special value |
|---|---|---|
| Insert | add(e) |
offer(e) â false |
| Remove head | remove() |
poll() â null |
| Examine head | element() |
peek() â null |
Key implementations: LinkedList, ArrayDeque, PriorityQueue.
2.5 `Deque` â double-ended queue (extends Queue)
Allows insertion/removal at both ends. Also usable as a Stack (LIFO).
| Operation | Front | Back |
|---|---|---|
| Insert | addFirst(e) / offerFirst(e) |
addLast(e) / offerLast(e) |
| Remove | removeFirst() / pollFirst() |
removeLast() / pollLast() |
| Examine | peekFirst() |
peekLast() |
| Stack use | push(e) = addFirst |
pop() = removeFirst |
Key implementations: ArrayDeque (preferred), LinkedList.
2.6 `Map` â key-value pairs
Map does not extend Collection. Key operations:
put(K, V),get(K),remove(K),containsKey(K),containsValue(V)keySet()âSet<K>,values()âCollection<V>,entrySet()âSet<Map.Entry<K,V>>- Java 8+:
getOrDefault,putIfAbsent,computeIfAbsent,merge,forEach
SortedMap adds: firstKey(), lastKey(), headMap(to), tailMap(from), subMap(from, to).
3. Practical Usage
When to use which interface?
| Scenario | Interface | Why |
|---|---|---|
| Ordered list of items, index access needed | List |
O(1) positional access |
| Unique elements, fast membership test | Set |
contains in O(1) (HashSet) |
| Key â value lookup | Map |
O(1) lookup by key |
| Task queue / event processing | Queue |
FIFO semantics |
| Undo/redo stack, browser history | Deque |
Both ends accessible |
| Sorted elements, range queries | SortedSet / SortedMap |
Natural or custom order |
Code to interface, not implementation
// â
Program to interface
List<String> names = new ArrayList<>();
Map<String, Integer> scores = new HashMap<>();
// â Over-specifying implementation
ArrayList<String> names = new ArrayList<>(); // loses flexibility
When NOT to use Collections
- Fixed-size numeric data with known dimensions â use primitive arrays
- Concurrent updates with high contention â use
java.util.concurrenttypes directly - Stream pipeline intermediate results â don't collect prematurely
4. Code Examples
Basic Example â Interface contracts in action
import java.util.*;
public class InterfaceContracts {
public static void main(String[] args) {
// List â order preserved, duplicates allowed
List<String> list = new ArrayList<>(List.of("banana", "apple", "apple", "cherry"));
System.out.println(list); // [banana, apple, apple, cherry]
System.out.println(list.get(1)); // apple
// Set â no duplicates, iteration order not guaranteed (HashSet)
Set<String> set = new HashSet<>(list);
System.out.println(set.size()); // 3 (apple deduplicated)
// Queue â FIFO
Queue<String> queue = new LinkedList<>(List.of("first", "second", "third"));
System.out.println(queue.poll()); // first
System.out.println(queue.peek()); // second
// Deque as stack â LIFO
Deque<String> stack = new ArrayDeque<>();
stack.push("a"); stack.push("b"); stack.push("c");
System.out.println(stack.pop()); // c (LIFO)
// Map â key-value
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 90); map.put("Bob", 85);
System.out.println(map.get("Alice")); // 90
System.out.println(map.getOrDefault("Charlie", 0)); // 0
}
}
Advanced Example â Writing generic algorithms against interfaces
public class CollectionUtils {
// Works with ANY List implementation
public static <T extends Comparable<T>> T findMax(List<T> list) {
if (list.isEmpty()) throw new NoSuchElementException();
T max = list.get(0);
for (T item : list) {
if (item.compareTo(max) > 0) max = item;
}
return max;
}
// Works with ANY Collection
public static <T> void printAll(Collection<T> collection) {
collection.forEach(System.out::println);
}
// Returns unmodifiable view â callers get List contract only
public static List<String> getNames() {
List<String> names = new ArrayList<>(List.of("Alice", "Bob", "Charlie"));
return Collections.unmodifiableList(names);
}
}
Common Pitfall â Mutating while iterating
List<String> items = new ArrayList<>(List.of("a", "b", "c", "b"));
// â ConcurrentModificationException!
for (String s : items) {
if (s.equals("b")) items.remove(s);
}
// â
Use Iterator's remove()
Iterator<String> it = items.iterator();
while (it.hasNext()) {
if (it.next().equals("b")) it.remove();
}
// â
Or use removeIf (Java 8+)
items.removeIf(s -> s.equals("b"));
5. Trade-offs
| Interface | ⥠Access Speed | đŸ Memory | đ§ Features | Use Case |
|---|---|---|---|---|
List |
O(1) index (array), O(n) search | Moderate | Index, sort, subList | Ordered sequences |
Set |
O(1) contains (hash), O(log n) (tree) | LowâModerate | Uniqueness | Membership test, deduplication |
Queue |
O(1) head operations | Low | FIFO semantics | Task scheduling |
Deque |
O(1) both ends | Low | Stack + Queue | Undo, sliding window |
Map |
O(1) by key (hash), O(log n) (tree) | ModerateâHigh | Key-value, merge ops | Caching, indexing |
6. Common Mistakes
1. Using `List` when uniqueness matters
// â Allows duplicates â bug if you need unique items
List<String> tags = new ArrayList<>();
tags.add("java"); tags.add("java"); // silent duplicate
// â
Use Set
Set<String> tags = new HashSet<>();
tags.add("java"); tags.add("java"); // size stays 1
2. Using `Stack` class (legacy)
// â Stack extends Vector â synchronized, legacy, avoid!
Stack<Integer> stack = new Stack<>();
// â
Use Deque
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1); stack.pop();
3. Ignoring `null` behavior differences
// TreeSet/TreeMap: null throws NullPointerException
TreeSet<String> sorted = new TreeSet<>();
sorted.add(null); // â NullPointerException â can't compare null
// HashSet: allows one null
HashSet<String> hashed = new HashSet<>();
hashed.add(null); // â
OK
4. Calling `remove(Object)` vs `remove(int)` on List
List<Integer> numbers = new ArrayList<>(List.of(1, 2, 3, 4));
numbers.remove(1); // removes by INDEX â [1, 3, 4]
numbers.remove(Integer.valueOf(3)); // removes by VALUE â [1, 4]
7. Senior-level Insights
Interface segregation in API design
Return the narrowest useful type from your methods. If callers only need to iterate, return Iterable<T>. If they need to check membership, return Collection<T>. Only return List if index access is truly needed.
`Iterable` vs `Collection` vs `List`
Iterable â can iterate (for-each)
Collection â + size, contains, add, remove
List â + index access, sort
Each step adds overhead (memory, complexity) â choose the minimum contract.
`Collections.unmodifiableXxx` vs `List.of` / `Set.of`
Collections.unmodifiableList(list)â view of a mutable list; underlying changes are visible!List.of(...)(Java 9+) â truly immutable; throws on any mutation attemptList.copyOf(collection)(Java 10+) â immutable copy, snapshot semantics
Performance implications of interface choice
Passing a LinkedList to a method that calls get(int) repeatedly is O(nÂČ). Accepting List<T> in your API doesn't guarantee random access â consider accepting RandomAccess marker or documenting requirements.
`SortedSet` and `SortedMap` consistency
The comparator must be consistent with equals: if comparator.compare(a, b) == 0 then a.equals(b) should be true. Otherwise, the Set contract (no duplicates) breaks silently.
8. Glossary
| Term | Definition |
|---|---|
| JCF | Java Collections Framework â the unified hierarchy of collection interfaces and implementations |
| Contract | The behavioral guarantee an interface makes to its callers |
| RandomAccess | Marker interface on ArrayList etc. indicating O(1) index access |
| FIFO | First-In-First-Out â insertion order determines removal order (Queue) |
| LIFO | Last-In-First-Out â most recently added item is removed first (Stack/Deque) |
| NavigableSet | Extension of SortedSet with methods for floor/ceiling/lower/higher queries |
| Fail-fast iterator | Iterator that throws ConcurrentModificationException if the collection is modified during iteration |
| Structural modification | Any change to the size of a collection (add/remove), as opposed to set |
9. Cheatsheet
- đ
Listâ ordered, index access, duplicates OK âArrayList(default) - đ
Setâ no duplicates, fastcontainsâHashSet(default) - đșïž
Mapâ key-value, fastgetby key âHashMap(default) - đŹ
Queueâ FIFO task processing âArrayDeque(preferred overLinkedList) - âïž
Dequeâ both ends accessible, also a stack âArrayDeque - â ïž
Stackclass is legacy â useArrayDequeinstead - â
Program to interface â
List<E>notArrayList<E>in signatures - đ Immutable collections â
List.of(),Set.of(),Map.of()(Java 9+) - đ«
TreeSet/TreeMaprejectnullkeys/elements - đ Mutate while iterating â use
iterator.remove()orremoveIf()
đź Games
10 questions