HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
4 Topics
Chapter•90 Minutes

Collections and Generics

Master List, Set, Map, Queue, Deque, iterators, sorting, generics, wildcards, type erasure, and collection selection.

List, Set, and Map

The Collections Framework provides reusable data structures and algorithms. List preserves order and allows duplicates. Set models uniqueness. Map associates keys with values.

List<String> names = new ArrayList<>();
names.add("A");
names.add("B");

Set<String> unique = new HashSet<>(names);

Map<String, Integer> counts = new HashMap<>();
counts.merge("java", 1, Integer::sum);

ArrayList is usually the default list. HashSet and HashMap provide average constant-time lookup under good hashing behavior. LinkedHashMap preserves insertion order, while TreeMap keeps keys sorted.

Key Takeaways
  • Choose collections based on required semantics.
  • ArrayList is a strong default for indexed/sequential lists.
  • Hash-based structures depend on correct equals and hashCode.

Queues, Deques, and Priority Queues

Queues represent ordered work. ArrayDeque is a strong general-purpose implementation for stack and queue operations. PriorityQueue orders elements according to priority.

Deque<String> stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
System.out.println(stack.pop());

Queue<String> queue = new ArrayDeque<>();
queue.offer("job-1");
queue.offer("job-2");
System.out.println(queue.poll());

PriorityQueue<Integer> priorities = new PriorityQueue<>();
priorities.offer(50);
priorities.offer(10);
System.out.println(priorities.poll());

A priority queue's internal array is not globally sorted; it maintains a heap property sufficient to retrieve the highest- or lowest-priority element efficiently.

Key Takeaways
  • ArrayDeque can serve as both stack and queue.
  • PriorityQueue exposes priority order through removal/peek, not full iteration order.
  • Use queue APIs such as offer and poll for clear semantics.

Generics and Wildcards

Generics provide compile-time type safety without repeated casts.

List<String> names = new ArrayList<>();
names.add("Java");

static double sum(List<? extends Number> values) {
    double total = 0;
    for (Number value : values) {
        total += value.doubleValue();
    }
    return total;
}

? extends T is useful when a structure is primarily a producer of T. ? super T is useful when it consumes T. This is commonly remembered as PECS: Producer Extends, Consumer Super.

Generic type information is largely erased at runtime.

PECS

Use extends when you mainly read values as a base type; use super when you mainly write values of a subtype.

Key Takeaways
  • Generics catch many type errors at compile time.
  • ? extends T is producer-oriented; ? super T is consumer-oriented.
  • Java generics use type erasure rather than fully reified generic types.

Sorting, Comparators, and Iterators

Java separates natural ordering from custom ordering. Comparable<T> defines a type's natural order; Comparator<T> supplies an external ordering strategy.

record Person(String name, int age) {}

List<Person> people = new ArrayList<>();
people.sort(
    Comparator.comparingInt(Person::age)
              .thenComparing(Person::name)
);

Iterators allow controlled traversal and, where supported, removal. The enhanced for loop uses an iterator for iterable collections.

Comparators should obey their contract; inconsistent ordering can cause unpredictable sorting behavior.

Key Takeaways
  • Use Comparable for natural order and Comparator for alternate orders.
  • Comparator contracts must be consistent.
  • Use collection APIs instead of reimplementing common traversal logic.