Java Collections Framework: List, Set, Map & Queue

What is the Collections Framework?

The Java Collections Framework (JCF) is a unified architecture for storing and manipulating groups of objects. It provides a set of interfaces, implementations, and algorithms that make it easy to work with data structures like lists, sets, queues, and maps without having to write them from scratch.

The core hierarchy of the Collections Framework looks like this:

java.lang.Iterable
  +-- java.util.Collection
        +-- List              (ordered, duplicates allowed)
        |     +-- ArrayList
        |     +-- LinkedList
        |     +-- Vector
        +-- Set               (no duplicates)
        |     +-- HashSet
        |     +-- LinkedHashSet
        |     +-- TreeSet (SortedSet)
        +-- Queue             (FIFO ordering)
              +-- LinkedList
              +-- PriorityQueue
              +-- Deque
                    +-- ArrayDeque
                    +-- LinkedList

java.util.Map                 (key-value pairs, separate hierarchy)
  +-- HashMap
  +-- LinkedHashMap
  +-- TreeMap (SortedMap)

Interfaces define the contract (what operations are supported). Implementations are the concrete classes you instantiate. For example, List is the interface; ArrayList and LinkedList are implementations.

Important: Iterable is the root of the hierarchy and provides iterator(). The Collection interface extends it and adds common operations such as add, remove, size, and contains. A Map is part of the framework but is not a subtype of Collection.

Note: Map does not extend Collection. It is a separate top-level interface in the framework.

Collection vs Collections

These two are frequently confused but serve very different purposes:

  • java.util.Collection — an interface. It is the root interface of the collection hierarchy. Classes like ArrayList, HashSet, and LinkedList implement it.
  • java.util.Collections — a utility class (all static methods). It provides algorithms like sorting, shuffling, binary search, and synchronization wrappers.
import java.util.*;

public class CollectionVsCollections {
    public static void main(String[] args) {
        // Collection (interface) — used via implementation
        Collection<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Charlie");
        names.add("Bob");

        // Collections (utility class) — static methods
        System.out.println("Before sort: " + names);
        Collections.sort((List<String>) names);
        System.out.println("After sort:  " + names);

        System.out.println("Max: " + Collections.max(names));
        System.out.println("Min: " + Collections.min(names));

        Collections.shuffle((List<String>) names);
        System.out.println("After shuffle: " + names);
    }
}
Before sort: [Alice, Charlie, Bob]
After sort: [Alice, Bob, Charlie]
Max: Charlie
Min: Alice
After shuffle: [Bob, Charlie, Alice]

List Interface

The List interface represents an ordered (sequenced) collection that allows duplicate elements. Elements can be accessed by their integer index (position). Key characteristics:

  • Maintains insertion order
  • Allows duplicate elements
  • Allows null elements
  • Provides positional access via get(int index)

ArrayList vs LinkedList Comparison

Feature ArrayList LinkedList
Internal Structure Dynamic array Doubly linked nodes
Random Access (get) O(1) — fast O(n) — slow
Add at end O(1) amortized O(1)
Insert / Delete in middle O(n) — shift needed O(1) once at node
Memory Less overhead More (node pointers)
Implements Deque No Yes
Best for Read-heavy workloads Frequent insert/delete

ArrayList

ArrayList is backed by a resizable array. When the array is full, a new array of 1.5× the size is allocated and all elements are copied. It is the most commonly used List implementation.

import java.util.*;

public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();

        // add elements
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Cherry");
        fruits.add("Date");
        System.out.println("List: " + fruits);

        // get element by index
        System.out.println("Index 1: " + fruits.get(1));

        // set (replace) element
        fruits.set(2, "Coconut");
        System.out.println("After set(2): " + fruits);

        // remove by index
        fruits.remove(0);
        System.out.println("After remove(0): " + fruits);

        // remove by value
        fruits.remove("Date");
        System.out.println("After remove('Date'): " + fruits);

        // contains check
        System.out.println("Contains Banana? " + fruits.contains("Banana"));

        // size
        System.out.println("Size: " + fruits.size());

        // iterate with enhanced for
        System.out.print("Elements: ");
        for (String f : fruits) {
            System.out.print(f + " ");
        }
        System.out.println();

        // iterate with Iterator
        Iterator<String> it = fruits.iterator();
        System.out.print("Iterator: ");
        while (it.hasNext()) {
            System.out.print(it.next() + " ");
        }
        System.out.println();
    }
}