The Java Collections Framework
A small set of interfaces describes how groups of objects behave, and many implementations trade memory, ordering and speed differently.
-
Java Basics
- Introduction to Java
- Setting Up Java and Writing Your First Program
- Variables, Data Types and Literals in Java
- Type Casting and Type Conversion in Java
- Operators and Expressions in Java
- Input and Output in Java
- Comments, Keywords and Naming Conventions in Java
- Control Flow in Java: if, else and switch
- Loops in Java: for, while and do-while
- Methods
- Arrays and Strings
-
OOP
- Classes and Objects in Java
- Constructors in Java
- The this Keyword in Java
- The static Keyword in Java
- Encapsulation in Java
- Access Modifiers in Java
- Inheritance in Java
- Method Overriding and super in Java
- Polymorphism in Java
- Abstraction, Abstract Classes and Interfaces in Java
- Composition, Aggregation and Association in Java
- The Object Lifecycle in Java
- Core Java
- Exception Handling
-
Collections
- The Java Collections Framework
- List in Java: ArrayList, LinkedList, Vector and Stack
- Set in Java: HashSet, LinkedHashSet and TreeSet
- Map in Java: HashMap, LinkedHashMap and TreeMap
- How HashMap Works Internally in Java
- Queue and Deque in Java: ArrayDeque and PriorityQueue
- Iterators in Java
- Comparable and Comparator in Java
- Collections Utilities and Choosing the Right Collection
- Generics
- Java 8+
- Stream API
- Date and Time
- File and I/O
-
Multithreading
- Threads in Java: Processes, Runnable and Thread
- Thread Lifecycle in Java
- Synchronization in Java: synchronized and volatile
- Locks and Atomic Classes in Java
- Race Conditions and Deadlocks in Java
- The Executor Framework and Thread Pools in Java
- Future and CompletableFuture in Java
- Concurrent Collections in Java
- The Java Memory Model
- JVM and Memory
- Advanced Java
- Networking
- JDBC
- Testing
What the framework is
The Collections Framework is a set of interfaces describing groups of objects, together with implementations of each and a group of utility classes. Writing code against the interfaces means the concrete class can be changed without touching anything else.
The interface hierarchy
Iterable
|
Collection
|
+-- List ordered, duplicates allowed, index based
+-- Set no duplicates
| +-- SortedSet -> NavigableSet
+-- Queue usually FIFO
+-- Deque both ends
Map (separate: not a Collection)
+-- SortedMap -> NavigableMapMapis deliberately not aCollection. A collection holds elements; a map holds key to value associations. It offerskeySet(),values()andentrySet()as collection views instead.
The main implementations
| Interface | Implementation | Ordering | Backed by |
|---|---|---|---|
List | ArrayList | Insertion order | A resizable array |
List | LinkedList | Insertion order | A doubly linked list |
Set | HashSet | None | A hash table |
Set | LinkedHashSet | Insertion order | Hash table plus links |
Set | TreeSet | Sorted | A red black tree |
Map | HashMap | None | A hash table |
Map | LinkedHashMap | Insertion or access order | Hash table plus links |
Map | TreeMap | Sorted by key | A red black tree |
Deque | ArrayDeque | Insertion order | A circular array |
Queue | PriorityQueue | By priority | A binary heap |
Common Collection methods
Collection<String> items = new ArrayList<>();
items.add("java");
items.addAll(List.of("sql", "html"));
items.remove("sql");
items.removeIf(value -> value.length() < 4);
System.out.println(items.size());
System.out.println(items.isEmpty());
System.out.println(items.contains("java"));
items.forEach(System.out::println);
items.clear();Program to the interface
List<String> names = new ArrayList<>(); // good
ArrayList<String> other = new ArrayList<>(); // needlessly specificDeclaring the variable as List means switching to LinkedList later is a one line change. Declare the most general type that supports what the code actually does.
Immutable collections
List<String> fixed = List.of("a", "b", "c"); // Java 9 and later
Set<Integer> codes = Set.of(1, 2, 3);
Map<String, Integer> ages = Map.of("Meera", 30, "Arun", 27);
List<String> copy = List.copyOf(mutableList); // an immutable snapshot
// fixed.add("d"); // throws UnsupportedOperationExceptionThese are genuinely immutable, reject null, and are more compact than a wrapped ArrayList. Use them for constants and for anything returned from a method that callers should not modify.
Generics keep collections type safe
List<String> safe = new ArrayList<>();
safe.add("java");
String value = safe.get(0); // no cast needed
List raw = new ArrayList(); // raw type, avoid
raw.add(42);
String broken = (String) raw.get(0); // compiles, throws at runtimeChoosing quickly
| You need | Use |
|---|---|
| An ordered list with fast access by index | ArrayList |
| Frequent adding and removing at both ends | ArrayDeque |
| Unique elements, order irrelevant | HashSet |
| Unique elements in insertion order | LinkedHashSet |
| Unique elements kept sorted | TreeSet |
| Key based lookup | HashMap |
| Key lookup with sorted keys or range queries | TreeMap |
| Always retrieve the smallest or largest first | PriorityQueue |
| A shared map under concurrency | ConcurrentHashMap |
Legacy classes
Vector, Stack and Hashtable predate the framework. Every method is synchronised, which is slower and does not make compound operations safe anyway. Use ArrayList, ArrayDeque and HashMap, and reach for java.util.concurrent when threads are involved.
Common mistakes
- Declaring variables with the concrete class instead of the interface.
- Using raw types and losing compile time checking.
- Calling
addon a list returned byList.oforArrays.asList. - Choosing
LinkedListfor indexed access, which is linear rather than constant. - Using a mutable object as a
HashSetelement or a map key.
Best practices
- Declare the interface, instantiate the implementation.
- Use
List.of,Set.ofandMap.offor fixed data. - Return an unmodifiable view or a copy from getters.
- Give the expected size to the constructor when it is known and large.
- Default to
ArrayListandHashMap, and change only when a measurement or a requirement says so.
Practice
- Why is
Mapnot a subtype ofCollection? - Choose a collection for: recently viewed pages, unique tags in alphabetical order, a task queue by priority.
- What happens when you call
addonList.of("a"), and why is that useful? - Rewrite
ArrayList<String> x = new ArrayList<>();to program to the interface and explain the benefit. - Give one reason not to use
Vectorin new code.
Conclusion
Learn the four interfaces first, then the trade offs between implementations. Program to the interface, prefer immutable collections for fixed data, and pick the implementation from how the data will actually be used.