48% complete
Java Collections Framework
The Java Collections Framework provides a unified architecture for representing and manipulating collections of objects. It includes interfaces, implementations, and algorithms that operate on collections.
What You'll Learn
- The core collection interfaces: List, Set, Queue, and Map
- Common implementation classes like ArrayList, HashSet, and HashMap
- How to iterate through collections using different approaches
- Understanding collection algorithms and utility methods
- Best practices for working with collections
Introduction to Collections
A collection is an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data. The Java Collections Framework provides a set of interfaces and classes that implement various data structures.
Benefits of the Collections Framework
- Reduces programming effort: Provides ready-made data structures and algorithms
- Increases program speed and quality: High-performance implementations
- Allows interoperability: Establishes a common language for passing collections
- Reduces effort to learn and use: Standard interfaces for collections
- Promotes software reuse: A standard means of collecting objects
The Collection Hierarchy
The Java Collections Framework is organized into a hierarchy of interfaces and classes:
Collection<E> / | \ / | \ / | \ List<E> Queue<E> Set<E> / \ | / \ / \ | / \ ArrayList<E> LinkedList<E> HashSet<E> SortedSet<E> | | | TreeSet<E> Deque<E> Map<K,V> / \ / \ HashMap<K,V> SortedMap<K,V> | TreeMap<K,V>
Core Collection Interfaces
The Java Collections Framework consists of these core interfaces:
Collection Interface
The root interface in the collection hierarchy. A collection represents a group of objects, known as its elements.
1import java.util.*;23public class CollectionDemo {4 public static void main(String[] args) {5 // Create a collection using ArrayList implementation6 Collection<String> collection = new ArrayList<>();78 // Adding elements9 collection.add("Apple");10 collection.add("Banana");11 collection.add("Cherry");1213 // Check size14 System.out.println("Size: " + collection.size()); // 31516 // Check if collection contains an element17 System.out.println("Contains 'Apple': " + collection.contains("Apple")); // true1819 // Remove an element20 collection.remove("Banana");2122 // Iterate over elements23 System.out.println("Elements:");24 for (String fruit : collection) {25 System.out.println(fruit);26 }2728 // Clear all elements29 collection.clear();30 System.out.println("Size after clear: " + collection.size()); // 031 }32}
List Interface
An ordered collection (also known as a sequence). Lists can contain duplicate elements and provide precise control over where each element is inserted.
1import java.util.*;23public class ListDemo {4 public static void main(String[] args) {5 // ArrayList - Resizable array implementation6 List<String> arrayList = new ArrayList<>();7 arrayList.add("Apple");8 arrayList.add("Banana");9 arrayList.add("Apple"); // Duplicates allowed1011 // Access by index12 System.out.println("Element at index 1: " + arrayList.get(1));1314 // Insert at specific position15 arrayList.add(1, "Orange");16 System.out.println("After insertion: " + arrayList);1718 // Replace element19 arrayList.set(0, "Apricot");20 System.out.println("After replacement: " + arrayList);2122 // Find index of element23 System.out.println("Index of 'Apple': " + arrayList.indexOf("Apple"));2425 // LinkedList - Doubly-linked list implementation26 List<String> linkedList = new LinkedList<>();27 linkedList.add("Red");28 linkedList.add("Green");29 linkedList.add("Blue");3031 // LinkedList as Deque32 LinkedList<String> linkedDeque = (LinkedList<String>) linkedList;33 linkedDeque.addFirst("First");34 linkedDeque.addLast("Last");3536 System.out.println("LinkedList: " + linkedList);37 }38}
ArrayList
Resizable array implementation of the List interface.
Pros:
- Fast random access (constant time)
- Fast iteration
- Good for storing and accessing data
Cons:
- Slow insertions/deletions in middle
- Resizing can be costly for large lists
LinkedList
Doubly-linked list implementation of the List and Deque interfaces.
Pros:
- Fast insertions/deletions anywhere in the list
- Implements Deque interface
- No resizing issues
Cons:
- Slow random access (linear time)
- More memory overhead
Set Interface
A collection that cannot contain duplicate elements. Sets model the mathematical set abstraction.
1import java.util.*;23public class SetDemo {4 public static void main(String[] args) {5 // HashSet - Uses hash table for storage6 Set<String> hashSet = new HashSet<>();7 hashSet.add("Apple");8 hashSet.add("Banana");9 hashSet.add("Cherry");10 hashSet.add("Apple"); // Duplicate ignored1112 System.out.println("HashSet: " + hashSet); // Order not guaranteed1314 // TreeSet - Stores elements in sorted order15 Set<String> treeSet = new TreeSet<>();16 treeSet.add("Zebra");17 treeSet.add("Dog");18 treeSet.add("Cat");19 treeSet.add("Ant");2021 System.out.println("TreeSet (sorted): " + treeSet); // Alphabetical order2223 // LinkedHashSet - Maintains insertion order24 Set<String> linkedHashSet = new LinkedHashSet<>();25 linkedHashSet.add("First");26 linkedHashSet.add("Second");27 linkedHashSet.add("Third");28 linkedHashSet.add("First"); // Duplicate ignored2930 System.out.println("LinkedHashSet: " + linkedHashSet); // Maintains insertion order31 }32}
HashSet
Backed by a hash table (HashMap). No guaranteed order.
Best for: Fast add/remove/contains operations.
TreeSet
Elements stored in sorted order. Backed by TreeMap.
Best for: Sorted data and range queries.
LinkedHashSet
Maintains insertion order. Backed by LinkedHashMap.
Best for: Predictable iteration order with fast access.
Map Interface
An object that maps keys to values. A map cannot contain duplicate keys.
1import java.util.*;23public class MapDemo {4 public static void main(String[] args) {5 // HashMap - Fast access, unordered6 Map<String, Integer> hashMap = new HashMap<>();7 hashMap.put("Apple", 10);8 hashMap.put("Banana", 20);9 hashMap.put("Cherry", 30);1011 // Retrieve a value by key12 System.out.println("Price of Apple: " + hashMap.get("Apple"));1314 // Check if key exists15 System.out.println("Contains Orange? " + hashMap.containsKey("Orange"));1617 // TreeMap - Sorted by keys18 Map<String, Integer> treeMap = new TreeMap<>();19 treeMap.put("Zebra", 100);20 treeMap.put("Dog", 50);21 treeMap.put("Cat", 40);2223 System.out.println("TreeMap (sorted by keys):");24 for (Map.Entry<String, Integer> entry : treeMap.entrySet()) {25 System.out.println(entry.getKey() + ": " + entry.getValue());26 }2728 // LinkedHashMap - Maintains insertion order29 Map<String, String> linkedHashMap = new LinkedHashMap<>();30 linkedHashMap.put("CEO", "John");31 linkedHashMap.put("CTO", "Mike");32 linkedHashMap.put("CFO", "Lisa");3334 System.out.println("LinkedHashMap (maintains insertion order):");35 for (String key : linkedHashMap.keySet()) {36 System.out.println(key + ": " + linkedHashMap.get(key));37 }38 }39}
HashMap
Hash table implementation. No guaranteed order.
Best for: Fast lookups by key.
TreeMap
Keys stored in sorted order. Red-black tree implementation.
Best for: Sorted data and range queries on keys.
LinkedHashMap
Maintains insertion order (or access order). Hash table with linked list.
Best for: Predictable iteration order with fast access.
Queue Interface
A collection designed for holding elements prior to processing. Queues typically order elements in a FIFO (first-in-first-out) manner.
1import java.util.*;23public class QueueDemo {4 public static void main(String[] args) {5 // LinkedList as Queue6 Queue<String> queue = new LinkedList<>();7 queue.offer("First"); // Add to the back8 queue.offer("Second");9 queue.offer("Third");1011 System.out.println("Queue: " + queue);1213 // Peek at the head of queue without removing14 System.out.println("Head of queue: " + queue.peek());1516 // Remove and return the head17 System.out.println("Removed: " + queue.poll());18 System.out.println("Queue after poll: " + queue);1920 // PriorityQueue - elements ordered by priority21 Queue<Integer> priorityQueue = new PriorityQueue<>();22 priorityQueue.offer(5);23 priorityQueue.offer(1);24 priorityQueue.offer(3);2526 System.out.println("Priority Queue (doesn't show sorted order): " + priorityQueue);2728 // Elements come out in priority order (natural ordering)29 System.out.print("Priority Queue polling order: ");30 while (!priorityQueue.isEmpty()) {31 System.out.print(priorityQueue.poll() + " "); // 1 3 532 }33 System.out.println();34 }35}
Deque Interface
A double-ended queue that supports element insertion and removal at both ends.
1import java.util.*;23public class DequeDemo {4 public static void main(String[] args) {5 // ArrayDeque implementation6 Deque<String> deque = new ArrayDeque<>();78 // Add to both ends9 deque.addFirst("First");10 deque.addLast("Last");1112 // Insert at front and back13 deque.offerFirst("New First");14 deque.offerLast("New Last");1516 System.out.println("Deque: " + deque);1718 // Examine elements at both ends19 System.out.println("First element: " + deque.getFirst());20 System.out.println("Last element: " + deque.getLast());2122 // Remove from both ends23 System.out.println("Remove first: " + deque.removeFirst());24 System.out.println("Remove last: " + deque.removeLast());2526 System.out.println("Deque after removal: " + deque);2728 // Using as a stack (LIFO)29 Deque<Integer> stack = new ArrayDeque<>();30 stack.push(1); // addFirst31 stack.push(2);32 stack.push(3);3334 System.out.println("Stack: " + stack);35 System.out.println("Pop: " + stack.pop()); // removeFirst36 System.out.println("Stack after pop: " + stack);37 }38}
Utility Methods and Algorithms
The Collections class provides static methods that operate on or return collections:
1import java.util.*;23public class CollectionsUtilDemo {4 public static void main(String[] args) {5 List<Integer> list = new ArrayList<>();6 list.add(3);7 list.add(1);8 list.add(5);9 list.add(2);10 list.add(4);1112 System.out.println("Original list: " + list);1314 // Sorting15 Collections.sort(list);16 System.out.println("Sorted list: " + list);1718 // Binary search (list must be sorted)19 int index = Collections.binarySearch(list, 3);20 System.out.println("Index of 3: " + index);2122 // Reverse23 Collections.reverse(list);24 System.out.println("Reversed list: " + list);2526 // Shuffle27 Collections.shuffle(list);28 System.out.println("Shuffled list: " + list);2930 // Min and Max31 System.out.println("Min: " + Collections.min(list));32 System.out.println("Max: " + Collections.max(list));3334 // Fill35 Collections.fill(list, 0);36 System.out.println("After fill with 0: " + list);3738 // Creating immutable collections39 List<String> immutableList = Collections.unmodifiableList(40 Arrays.asList("One", "Two", "Three")41 );42 System.out.println("Immutable list: " + immutableList);4344 // Trying to modify will throw UnsupportedOperationException45 // immutableList.add("Four"); // This would cause an exception46 }47}
Iterating Through Collections
Java provides several ways to iterate through collections:
1import java.util.*;2import java.util.function.Consumer;34public class IterationDemo {5 public static void main(String[] args) {6 List<String> list = Arrays.asList("Apple", "Banana", "Cherry", "Date");78 System.out.println("Using enhanced for loop:");9 for (String item : list) {10 System.out.println(item);11 }1213 System.out.println("\nUsing Iterator:");14 Iterator<String> iterator = list.iterator();15 while (iterator.hasNext()) {16 String item = iterator.next();17 System.out.println(item);18 }1920 System.out.println("\nUsing forEach method with lambda (Java 8+):");21 list.forEach(item -> System.out.println(item));2223 System.out.println("\nUsing forEach method with method reference (Java 8+):");24 list.forEach(System.out::println);2526 System.out.println("\nUsing Stream API (Java 8+):");27 list.stream()28 .filter(s -> s.startsWith("B") || s.startsWith("C"))29 .map(String::toUpperCase)30 .forEach(System.out::println);31 }32}
Common Collection Operations
Here are some common operations performed with collections:
1import java.util.*;2import java.util.stream.Collectors;34public class CommonOperations {5 public static void main(String[] args) {6 // Creating collections7 List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));8 Set<String> uniqueNames = new HashSet<>(Arrays.asList("Alice", "Bob", "Charlie"));9 Map<String, Integer> scores = new HashMap<>();10 scores.put("Alice", 95);11 scores.put("Bob", 85);12 scores.put("Charlie", 90);1314 // Converting between collection types15 Set<Integer> numberSet = new HashSet<>(numbers);16 List<String> nameList = new ArrayList<>(uniqueNames);1718 // Finding elements19 boolean containsThree = numbers.contains(3);20 boolean containsDave = uniqueNames.contains("Dave");2122 System.out.println("numbers contains 3: " + containsThree);23 System.out.println("uniqueNames contains Dave: " + containsDave);2425 // Removing elements26 numbers.remove(Integer.valueOf(3)); // Remove by value, not index27 System.out.println("After removing 3: " + numbers);2829 // Filtering with Stream API (Java 8+)30 List<Integer> evenNumbers = numbers.stream()31 .filter(n -> n % 2 == 0)32 .collect(Collectors.toList());33 System.out.println("Even numbers: " + evenNumbers);3435 // Finding max value36 Optional<Integer> maxScore = scores.values().stream().max(Integer::compare);37 System.out.println("Max score: " + maxScore.orElse(0));3839 // Joining elements40 String joined = String.join(", ", nameList);41 System.out.println("Joined names: " + joined);4243 // Combining collections44 List<String> moreNames = Arrays.asList("Dave", "Eve");45 List<String> combined = new ArrayList<>(nameList);46 combined.addAll(moreNames);47 System.out.println("Combined list: " + combined);48 }49}
Performance Considerations
Operation | ArrayList | LinkedList | HashSet | TreeSet | HashMap | TreeMap |
---|---|---|---|---|---|---|
add/put | O(1) amortized | O(1) | O(1) | O(log n) | O(1) | O(log n) |
contains/containsKey | O(n) | O(n) | O(1) | O(log n) | O(1) | O(log n) |
get | O(1) | O(n) | N/A | N/A | O(1) | O(log n) |
remove | O(n) | O(1) | O(1) | O(log n) | O(1) | O(log n) |
iteration | O(n) | O(n) | O(n) | O(n) | O(n) | O(n) |
Best Practices
Best Practices for Using Collections
- Use the interfaces (List, Set, Map) in variable declarations, not the implementations
- Choose the right collection implementation based on your use case
- Use generics to ensure type safety
- Consider using immutable collections for thread safety
- Be aware of performance characteristics when choosing a collection
- Use the Stream API for complex data processing
- Initialize collections with expected capacity when known
- Implement equals() and hashCode() properly for custom objects stored in collections
Summary
In this tutorial, you've learned:
- The core interfaces in the Java Collections Framework
- Implementation classes for different collection types
- How to choose the right collection for your needs
- Common operations and algorithms for collections
- Performance considerations for different collection types
- Best practices for working with collections
The Java Collections Framework is a fundamental part of Java programming, providing efficient, reusable data structures. Understanding how to use these collections effectively will help you write better Java code.
Practice Exercise
Create a program that compares the performance of different collection types (ArrayList, LinkedList, HashSet, TreeSet) for common operations like insertion, search, and deletion with large datasets. Analyze the results to understand the strengths and weaknesses of each collection type.
Related Tutorials
Learn about fixed-size collections in Java.
Learn moreUnderstand how to create type-safe collections.
Learn moreProcess collections of objects in a functional style.
Learn more