Java Collections Framework: Internal Implementation
The Java Collections Framework provides a unified architecture for managing collections such as lists, sets, maps, and queues. This article explores the internal implementation of key collection classes, their underlying data structures, time complexities, and practical examples to demonstrate their usage. The focus is on the List, Set, Map, and Queue interfaces, their primary implementations, and their suitability for various use cases.
1. List Interface represents an ordered collection that allows duplicates. Its main implementations are ArrayList, LinkedList, and Vector.
1.1 ArrayList
import java.util.ArrayList;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
// Adding elements (O(1) amortized)
list.add("Apple"); // [Apple]
list.add("Banana"); // [Apple, Banana]
list.add(1, "Orange"); // [Apple, Orange, Banana] - Shifts elements (O(n))
// Accessing elements (O(1))
System.out.println("Element at index 1: " + list.get(1)); // Output: Orange
// Removing element (O(n) due to shifting)
list.remove(0); // [Orange, Banana]
System.out.println("List after removal: " + list); // Output: [Orange, Banana]
}
}
1.2 LinkedList
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
// Adding elements (O(1) at ends)
list.addFirst("Apple"); // [Apple]
list.addLast("Banana"); // [Apple, Banana]
list.add(1, "Orange"); // [Apple, Orange, Banana] - Traverses to index (O(n))
// Accessing element (O(n) due to traversal)
System.out.println("Element at index 1: " + list.get(1)); // Output: Orange
// Removing element (O(1) at ends)
list.removeFirst(); // [Orange, Banana]
System.out.println("List after removal: " + list); // Output: [Orange, Banana]
}
}
1.3 Vector
import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
vector.add("Apple"); // Synchronized (O(1) amortized)
vector.add("Banana");
System.out.println("Vector: " + vector); // Output: [Apple, Banana]
// Thread-safe operation
new Thread(() -> vector.add("Orange")).start();
// Eventually: [Apple, Banana, Orange]
}
}
2. Set Interface represents a collection with no duplicates. Its main implementations are HashSet, LinkedHashSet, and TreeSet.
2.1 HashSet
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
// Adding elements (O(1) average)
set.add("Apple"); // Hashed to a bucket
set.add("Banana");
set.add("Apple"); // Duplicate ignored
System.out.println("Set: " + set); // Output: [Apple, Banana] (order not guaranteed)
// Checking containment (O(1) average)
System.out.println("Contains Banana? " + set.contains("Banana")); // Output: true
// Removing element (O(1) average)
set.remove("Apple");
System.out.println("Set after removal: " + set); // Output: [Banana]
}
}
2.2 LinkedHashSet
import java.util.LinkedHashSet;
public class LinkedHashSetExample {
public static void main(String[] args) {
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Orange");
System.out.println("Set: " + set); // Output: [Apple, Banana, Orange] (insertion order)
set.remove("Banana");
System.out.println("Set after removal: " + set); // Output: [Apple, Orange]
}
}
2.3 TreeSet
import java.util.TreeSet;
public class TreeSetExample {
public static void main(String[] args) {
TreeSet<String> set = new TreeSet<>();
set.add("Banana");
set.add("Apple");
set.add("Orange");
System.out.println("Set: " + set); // Output: [Apple, Banana, Orange] (sorted order)
// Range operations
System.out.println("Elements >= Banana: " + set.tailSet("Banana")); // Output: [Banana, Orange]
}
}
3. Map Interface stores key-value pairs with unique keys. Its main implementations are HashMap, LinkedHashMap, TreeMap, and ConcurrentHashMap.
3.1 HashMap
import java.util.HashMap;
public class HashMapExample {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
// Adding key-value pairs (O(1) average)
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Apple", 3); // Overwrites value
System.out.println("Map: " + map); // Output: {Apple=3, Banana=2} (order not guaranteed)
// Retrieving value (O(1) average)
System.out.println("Value for Banana: " + map.get("Banana")); // Output: 2
// Removing key (O(1) average)
map.remove("Apple");
System.out.println("Map after removal: " + map); // Output: {Banana=2}
}
}
Recommended by LinkedIn
3.2 LinkedHashMap
import java.util.LinkedHashMap;
public class LinkedHashMapExample {
public static void main(String[] args) {
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Orange", 3);
System.out.println("Map: " + map); // Output: {Apple=1, Banana=2, Orange=3} (insertion order)
// Access order example
LinkedHashMap<String, Integer> accessOrderMap = new LinkedHashMap<>(16, 0.75f, true);
accessOrderMap.put("Apple", 1);
accessOrderMap.put("Banana", 2);
accessOrderMap.get("Apple"); // Access moves Apple to end
System.out.println("Access order: " + accessOrderMap); // Output: {Banana=2, Apple=1}
}
}
3.3 TreeMap
import java.util.TreeMap;
public class TreeMapExample {
public static void main(String[] args) {
TreeMap<String, Integer> map = new TreeMap<>();
map.put("Banana", 2);
map.put("Apple", 1);
map.put("Orange", 3);
System.out.println("Map: " + map); // Output: {Apple=1, Banana=2, Orange=3} (sorted by keys)
// Range operations
System.out.println("Keys >= Banana: " + map.tailMap("Banana")); // Output: {Banana=2, Orange=3}
}
}
3.4 ConcurrentHashMap
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
// Thread-safe operations
new Thread(() -> map.put("Orange", 3)).start();
System.out.println("Map: " + map); // Eventually: {Apple=1, Banana=2, Orange=3}
// Atomic operation
map.putIfAbsent("Apple", 4); // Ignored (key exists)
System.out.println("Map after putIfAbsent: " + map);
}
}
4. Queue and Deque Interfaces support FIFO (First-In-First-Out) and LIFO (Last-In-First-Out) operations. Key implementations are PriorityQueue, ArrayDeque, and ConcurrentLinkedQueue.
4.1 PriorityQueue
import java.util.PriorityQueue;
public class PriorityQueueExample {
public static void main(String[] args) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
queue.offer(3); // [3]
queue.offer(1); // [1, 3]
queue.offer(2); // [1, 2, 3]
System.out.println("Queue: " + queue); // Output: [1, 2, 3] (heap order)
// Remove smallest element (O(log n))
System.out.println("Polled: " + queue.poll()); // Output: 1
System.out.println("Queue after poll: " + queue); // Output: [2, 3]
}
}
4.2 ArrayDeque
import java.util.ArrayDeque;
public class ArrayDequeExample {
public static void main(String[] args) {
ArrayDeque<String> deque = new ArrayDeque<>();
deque.addFirst("Apple"); // [Apple]
deque.addLast("Banana"); // [Apple, Banana]
System.out.println("Deque: " + deque); // Output: [Apple, Banana]
// Remove from front (O(1))
System.out.println("Polled: " + deque.pollFirst()); // Output: Apple
System.out.println("Deque after poll: " + deque); // Output: [Banana]
}
}
4.3 ConcurrentLinkedQueue
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("Apple");
queue.offer("Banana");
System.out.println("Queue: " + queue); // Output: [Apple, Banana]
// Thread-safe poll
new Thread(() -> System.out.println("Polled: " + queue.poll())).start();
// Eventually: [Banana]
}
}
5. For multi-threaded applications, Java provides thread-safe collections in the java.util.concurrent package:
6. Summary of Use Cases and Performance
7. Key Notes
#JavaCollections #JavaProgramming #CollectionsFramework #JavaDevelopment #DataStructures #JavaTutorial #ArrayList #HashMap #TreeSet #ConcurrentHashMap #JavaCode #Programming #SoftwareDevelopment #JavaExamples #CodingTips #LearnJava #TechTutorials #JavaPerformance #DataStructuresAndAlgorithms #JavaConcurrency
Why even mentioning Vector? Lagacy ... at best... do not use it anymore for about 15 years+ If you need a thread-safe variant use CopyOnWriteArrayList instead...