The Collections Framework

An overview of List, Set, Queue, Deque and Map, and when to use each.

The Java Collections Framework is a set of interfaces and classes in java.util for storing groups of objects. You have already met ArrayList and HashMap. This lesson shows the whole family and how to choose between them.

CollectioninterfaceListordered, allows duplicatesArrayListLinkedListSetno duplicatesHashSetLinkedHashSetTreeSetQueueprocess in orderPriorityQueueArrayDequeMapkey-value, separate familyHashMapLinkedHashMapTreeMap
The main collection interfaces (top) and their common implementations

Choosing a collection

NeedUse
Ordered list, fast access by indexArrayList
Many inserts and removals at both endsArrayDeque (or LinkedList)
Unique items, order does not matterHashSet
Unique items, keep insertion orderLinkedHashSet
Unique items, always sortedTreeSet
Always take the smallest (or highest priority) nextPriorityQueue
Look up values by keyHashMap (sorted keys: TreeMap)

Sets

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        String[] visits = {"Delhi", "Agra", "Delhi", "Jaipur", "Agra"};

        Set<String> inOrder = new LinkedHashSet<>();
        Set<String> sorted = new TreeSet<>();
        for (String city : visits) {
            inOrder.add(city);
            sorted.add(city);
        }
        System.out.println(inOrder);
        System.out.println(sorted);
        System.out.println(inOrder.contains("Agra"));

        TreeSet<Integer> scores = new TreeSet<>(Set.of(45, 72, 88, 91, 60));
        System.out.println(scores.first() + " " + scores.last());
        System.out.println(scores.headSet(70));     // everything below 70
    }
}
Output
[Delhi, Agra, Jaipur]
[Agra, Delhi, Jaipur]
true
45 91
[45, 60]

Queues and stacks with ArrayDeque

A queue is first in, first out (FIFO), like a line at a ticket counter. A stack is last in, first out (LIFO), like a pile of plates. ArrayDeque can be both.

offer("A")enters at the backoffer("B")offer("C")poll()returns "A"
Queue (FIFO): items leave in the order they arrived
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Queue;

public class Main {
    public static void main(String[] args) {
        Queue<String> line = new ArrayDeque<>();
        line.offer("Asha");
        line.offer("Ravi");
        line.offer("Meera");
        System.out.println(line.peek());     // look at the front
        System.out.println(line.poll());     // remove the front
        System.out.println(line);

        Deque<Integer> stack = new ArrayDeque<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        System.out.println(stack.pop());     // last in, first out
        System.out.println(stack);
    }
}
Output
Asha
Asha
[Ravi, Meera]
3
[2, 1]

PriorityQueue

A PriorityQueue always hands out the smallest element first (or the "highest priority" one, if you give it a comparator).

import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        PriorityQueue<Integer> tasks = new PriorityQueue<>();
        tasks.add(30);
        tasks.add(5);
        tasks.add(18);
        tasks.add(1);
        while (!tasks.isEmpty()) {
            System.out.print(tasks.poll() + " ");
        }
        System.out.println();
    }
}
Output
1 5 18 30 

Iterator and the Collections class

Every collection can be walked with an Iterator, which also lets you remove items safely while looping. The Collections helper class has ready-made algorithms.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> nums = new ArrayList<>(List.of(4, 9, 2, 7, 6, 1));

        Iterator<Integer> it = nums.iterator();
        while (it.hasNext()) {
            if (it.next() % 2 == 0) it.remove();    // safe removal
        }
        System.out.println(nums);

        Collections.sort(nums);
        System.out.println(nums);
        Collections.reverse(nums);
        System.out.println(nums);
        System.out.println(Collections.max(nums) + " " + Collections.frequency(nums, 7));

        List<String> fixed = List.of("read", "only");
        try {
            fixed.add("more");
        } catch (UnsupportedOperationException e) {
            System.out.println("List.of(...) lists cannot be changed");
        }
    }
}
Output
[9, 7, 1]
[1, 7, 9]
[9, 7, 1]
9 1
List.of(...) lists cannot be changed