Master Java Collections: Lists, Sets, Queues, Maps & Their Core Implementations
This article provides a comprehensive overview of Java's collection framework, explaining the differences between List, Set, Queue, and Map, detailing their underlying data structures, and offering best practices for safe traversal and modification.
#Java Collections Overview
Java collections, also called containers, are derived from two main interfaces: Collection for single elements and Map for key‑value pairs. Collection has three primary sub‑interfaces: List, Set, and Queue.
Java collection framework diagram:
Note: the diagram shows only major inheritance relationships; many abstract classes and helper classes are omitted.
# Differences among List, Set, Queue, Map
List: ordered, allows duplicates.
Set: unordered, no duplicates.
Queue: ordered according to a specific rule, allows duplicates.
Map: stores key‑value pairs; keys are unordered and unique, values are unordered and may duplicate.
# Underlying data structures of the collection framework
Below are the concrete classes for each interface.
# List
ArrayList – backed by an Object[] array.
Vector – backed by an Object[] array.
LinkedList – doubly linked list (circular list before JDK 1.7).
# Set
HashSet – implements Set using a HashMap.
LinkedHashSet – subclass of HashSet, maintains insertion order via a LinkedHashMap.
TreeSet – uses a red‑black tree to provide ordered, unique elements.
# Queue
PriorityQueue – implements a binary heap using an Object[] array.
ArrayQueue – uses an Object[] array with two pointers.
# Map
HashMap – before JDK 1.8 a bucket is an array plus linked list; after JDK 1.8 long chains are transformed into red‑black trees.
LinkedHashMap – extends HashMap and adds a doubly linked list to preserve insertion order.
Hashtable – array plus linked list for collision handling.
TreeMap – red‑black tree implementation.
Collection Traversal Tips
According to the Alibaba Java Development Manual, do not perform remove/add operations inside a foreach loop. Use an Iterator’s remove method, and lock the Iterator when concurrent modifications are possible.
Although foreach is syntactic sugar for an Iterator, calling collection.remove/add directly bypasses the Iterator’s remove/add, causing the Iterator to detect unexpected modifications and throw a ConcurrentModificationException (fail‑fast behavior).
Fail‑fast collections throw ConcurrentModificationException when modified during iteration, even in single‑threaded contexts.
Since Java 8, you can use Collection#removeIf() to delete elements that match a predicate, e.g.:
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; ++i) {
list.add(i);
}
list.removeIf(filter -> filter % 2 == 0); // delete all even numbers
System.out.println(list); // [1, 3, 5, 7, 9]Other traversal options include using a classic for loop or employing fail‑safe collections from java.util.concurrent, which do not throw ConcurrentModificationException.
Java Interview Crash Guide
Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
