Progress12 of 25 topics

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.

java
1import java.util.*;
2
3public class CollectionDemo {
4 public static void main(String[] args) {
5 // Create a collection using ArrayList implementation
6 Collection<String> collection = new ArrayList<>();
7
8 // Adding elements
9 collection.add("Apple");
10 collection.add("Banana");
11 collection.add("Cherry");
12
13 // Check size
14 System.out.println("Size: " + collection.size()); // 3
15
16 // Check if collection contains an element
17 System.out.println("Contains 'Apple': " + collection.contains("Apple")); // true
18
19 // Remove an element
20 collection.remove("Banana");
21
22 // Iterate over elements
23 System.out.println("Elements:");
24 for (String fruit : collection) {
25 System.out.println(fruit);
26 }
27
28 // Clear all elements
29 collection.clear();
30 System.out.println("Size after clear: " + collection.size()); // 0
31 }
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.

java
1import java.util.*;
2
3public class ListDemo {
4 public static void main(String[] args) {
5 // ArrayList - Resizable array implementation
6 List<String> arrayList = new ArrayList<>();
7 arrayList.add("Apple");
8 arrayList.add("Banana");
9 arrayList.add("Apple"); // Duplicates allowed
10
11 // Access by index
12 System.out.println("Element at index 1: " + arrayList.get(1));
13
14 // Insert at specific position
15 arrayList.add(1, "Orange");
16 System.out.println("After insertion: " + arrayList);
17
18 // Replace element
19 arrayList.set(0, "Apricot");
20 System.out.println("After replacement: " + arrayList);
21
22 // Find index of element
23 System.out.println("Index of 'Apple': " + arrayList.indexOf("Apple"));
24
25 // LinkedList - Doubly-linked list implementation
26 List<String> linkedList = new LinkedList<>();
27 linkedList.add("Red");
28 linkedList.add("Green");
29 linkedList.add("Blue");
30
31 // LinkedList as Deque
32 LinkedList<String> linkedDeque = (LinkedList<String>) linkedList;
33 linkedDeque.addFirst("First");
34 linkedDeque.addLast("Last");
35
36 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.

java
1import java.util.*;
2
3public class SetDemo {
4 public static void main(String[] args) {
5 // HashSet - Uses hash table for storage
6 Set<String> hashSet = new HashSet<>();
7 hashSet.add("Apple");
8 hashSet.add("Banana");
9 hashSet.add("Cherry");
10 hashSet.add("Apple"); // Duplicate ignored
11
12 System.out.println("HashSet: " + hashSet); // Order not guaranteed
13
14 // TreeSet - Stores elements in sorted order
15 Set<String> treeSet = new TreeSet<>();
16 treeSet.add("Zebra");
17 treeSet.add("Dog");
18 treeSet.add("Cat");
19 treeSet.add("Ant");
20
21 System.out.println("TreeSet (sorted): " + treeSet); // Alphabetical order
22
23 // LinkedHashSet - Maintains insertion order
24 Set<String> linkedHashSet = new LinkedHashSet<>();
25 linkedHashSet.add("First");
26 linkedHashSet.add("Second");
27 linkedHashSet.add("Third");
28 linkedHashSet.add("First"); // Duplicate ignored
29
30 System.out.println("LinkedHashSet: " + linkedHashSet); // Maintains insertion order
31 }
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.

java
1import java.util.*;
2
3public class MapDemo {
4 public static void main(String[] args) {
5 // HashMap - Fast access, unordered
6 Map<String, Integer> hashMap = new HashMap<>();
7 hashMap.put("Apple", 10);
8 hashMap.put("Banana", 20);
9 hashMap.put("Cherry", 30);
10
11 // Retrieve a value by key
12 System.out.println("Price of Apple: " + hashMap.get("Apple"));
13
14 // Check if key exists
15 System.out.println("Contains Orange? " + hashMap.containsKey("Orange"));
16
17 // TreeMap - Sorted by keys
18 Map<String, Integer> treeMap = new TreeMap<>();
19 treeMap.put("Zebra", 100);
20 treeMap.put("Dog", 50);
21 treeMap.put("Cat", 40);
22
23 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 }
27
28 // LinkedHashMap - Maintains insertion order
29 Map<String, String> linkedHashMap = new LinkedHashMap<>();
30 linkedHashMap.put("CEO", "John");
31 linkedHashMap.put("CTO", "Mike");
32 linkedHashMap.put("CFO", "Lisa");
33
34 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.

java
1import java.util.*;
2
3public class QueueDemo {
4 public static void main(String[] args) {
5 // LinkedList as Queue
6 Queue<String> queue = new LinkedList<>();
7 queue.offer("First"); // Add to the back
8 queue.offer("Second");
9 queue.offer("Third");
10
11 System.out.println("Queue: " + queue);
12
13 // Peek at the head of queue without removing
14 System.out.println("Head of queue: " + queue.peek());
15
16 // Remove and return the head
17 System.out.println("Removed: " + queue.poll());
18 System.out.println("Queue after poll: " + queue);
19
20 // PriorityQueue - elements ordered by priority
21 Queue<Integer> priorityQueue = new PriorityQueue<>();
22 priorityQueue.offer(5);
23 priorityQueue.offer(1);
24 priorityQueue.offer(3);
25
26 System.out.println("Priority Queue (doesn't show sorted order): " + priorityQueue);
27
28 // 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 5
32 }
33 System.out.println();
34 }
35}

Deque Interface

A double-ended queue that supports element insertion and removal at both ends.

java
1import java.util.*;
2
3public class DequeDemo {
4 public static void main(String[] args) {
5 // ArrayDeque implementation
6 Deque<String> deque = new ArrayDeque<>();
7
8 // Add to both ends
9 deque.addFirst("First");
10 deque.addLast("Last");
11
12 // Insert at front and back
13 deque.offerFirst("New First");
14 deque.offerLast("New Last");
15
16 System.out.println("Deque: " + deque);
17
18 // Examine elements at both ends
19 System.out.println("First element: " + deque.getFirst());
20 System.out.println("Last element: " + deque.getLast());
21
22 // Remove from both ends
23 System.out.println("Remove first: " + deque.removeFirst());
24 System.out.println("Remove last: " + deque.removeLast());
25
26 System.out.println("Deque after removal: " + deque);
27
28 // Using as a stack (LIFO)
29 Deque<Integer> stack = new ArrayDeque<>();
30 stack.push(1); // addFirst
31 stack.push(2);
32 stack.push(3);
33
34 System.out.println("Stack: " + stack);
35 System.out.println("Pop: " + stack.pop()); // removeFirst
36 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:

java
1import java.util.*;
2
3public 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);
11
12 System.out.println("Original list: " + list);
13
14 // Sorting
15 Collections.sort(list);
16 System.out.println("Sorted list: " + list);
17
18 // Binary search (list must be sorted)
19 int index = Collections.binarySearch(list, 3);
20 System.out.println("Index of 3: " + index);
21
22 // Reverse
23 Collections.reverse(list);
24 System.out.println("Reversed list: " + list);
25
26 // Shuffle
27 Collections.shuffle(list);
28 System.out.println("Shuffled list: " + list);
29
30 // Min and Max
31 System.out.println("Min: " + Collections.min(list));
32 System.out.println("Max: " + Collections.max(list));
33
34 // Fill
35 Collections.fill(list, 0);
36 System.out.println("After fill with 0: " + list);
37
38 // Creating immutable collections
39 List<String> immutableList = Collections.unmodifiableList(
40 Arrays.asList("One", "Two", "Three")
41 );
42 System.out.println("Immutable list: " + immutableList);
43
44 // Trying to modify will throw UnsupportedOperationException
45 // immutableList.add("Four"); // This would cause an exception
46 }
47}

Iterating Through Collections

Java provides several ways to iterate through collections:

java
1import java.util.*;
2import java.util.function.Consumer;
3
4public class IterationDemo {
5 public static void main(String[] args) {
6 List<String> list = Arrays.asList("Apple", "Banana", "Cherry", "Date");
7
8 System.out.println("Using enhanced for loop:");
9 for (String item : list) {
10 System.out.println(item);
11 }
12
13 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 }
19
20 System.out.println("\nUsing forEach method with lambda (Java 8+):");
21 list.forEach(item -> System.out.println(item));
22
23 System.out.println("\nUsing forEach method with method reference (Java 8+):");
24 list.forEach(System.out::println);
25
26 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:

java
1import java.util.*;
2import java.util.stream.Collectors;
3
4public class CommonOperations {
5 public static void main(String[] args) {
6 // Creating collections
7 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);
13
14 // Converting between collection types
15 Set<Integer> numberSet = new HashSet<>(numbers);
16 List<String> nameList = new ArrayList<>(uniqueNames);
17
18 // Finding elements
19 boolean containsThree = numbers.contains(3);
20 boolean containsDave = uniqueNames.contains("Dave");
21
22 System.out.println("numbers contains 3: " + containsThree);
23 System.out.println("uniqueNames contains Dave: " + containsDave);
24
25 // Removing elements
26 numbers.remove(Integer.valueOf(3)); // Remove by value, not index
27 System.out.println("After removing 3: " + numbers);
28
29 // 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);
34
35 // Finding max value
36 Optional<Integer> maxScore = scores.values().stream().max(Integer::compare);
37 System.out.println("Max score: " + maxScore.orElse(0));
38
39 // Joining elements
40 String joined = String.join(", ", nameList);
41 System.out.println("Joined names: " + joined);
42
43 // Combining collections
44 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

OperationArrayListLinkedListHashSetTreeSetHashMapTreeMap
add/putO(1) amortizedO(1)O(1)O(log n)O(1)O(log n)
contains/containsKeyO(n)O(n)O(1)O(log n)O(1)O(log n)
getO(1)O(n)N/AN/AO(1)O(log n)
removeO(n)O(1)O(1)O(log n)O(1)O(log n)
iterationO(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 more

Understand how to create type-safe collections.

Learn more

Process collections of objects in a functional style.

Learn more