Java Collections

List, Map, Set & Generics

The Java Collections Framework — the type-safe, resizable data structures you'll reach for in nearly every program.

Java 21 ✓ Core Concepts 4 Topics
01

Arrays

Arrays are fixed-size and hold a single type. Their length is set at creation and never changes — for a resizable list, you use ArrayList instead.

Java — Arrays
int[] nums = {5, 2, 8, 1};
nums.length;              // 4 — a field, not a method
nums[0];                 // 5

String[] names = new String[3];   // [null, null, null]
names[0] = "Alice";

// Arrays utility class
Arrays.sort(nums);          // [1, 2, 5, 8] — sorts in place
Arrays.toString(nums);      // "[1, 2, 5, 8]"

// 2D array
int[][] grid = {{1, 2}, {3, 4}};
grid[1][0];             // 3
02

List & ArrayList

List is the interface; ArrayList is the everyday implementation — a resizable array. Program to the interface (List<String> x = new ArrayList<>()) so you can swap the implementation later.

Java — ArrayList
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.get(0);            // "Alice"
names.size();             // 2
names.contains("Bob");   // true
names.remove("Alice");  // removes by value

// iterate
for (String n : names) System.out.println(n);

// immutable list literal (Java 9+)
List<Integer> fixed = List.of(1, 2, 3);   // cannot be modified
Collections hold objects, not primitivesList<int> is illegal. Use the wrapper type: List<Integer>. Java autoboxes the primitives for you.
03

Map & Set

HashMap stores key-value pairs with O(1) average lookup; HashSet stores unique values only. Both are unordered — use LinkedHashMap/TreeMap when order matters.

Java — HashMap & HashSet
Map<String, Integer> scores = new HashMap<>();
scores.put("alice", 95);
scores.put("bob", 88);
scores.get("alice");           // 95
scores.getOrDefault("x", 0);  // 0 — no crash on missing key
scores.containsKey("bob");     // true

// count occurrences — the classic merge idiom
scores.merge("alice", 1, Integer::sum);

Set<Integer> unique = new HashSet<>();
unique.add(1); unique.add(1); unique.add(2);
unique.size();                // 2 — duplicate ignored
04

Generics

Generics let a class or method work with any type while keeping full compile-time type safety. The <String> in List<String> means the compiler rejects anything but Strings — no casts, no runtime surprises.

Java — Generic Method & Class
// Generic method — <T> means "works for any type T"
static <T> T firstOf(List<T> list) {
    return list.get(0);
}
String s = firstOf(List.of("a", "b"));   // T inferred as String

// Generic class — a type-safe box
class Box<T> {
    private T value;
    void set(T v) { value = v; }
    T get() { return value; }
}
Box<Integer> box = new Box<>();
box.set(42);
int n = box.get();       // no cast needed — compiler knows it's Integer
Before generics (Java 5), collections held raw Object and you cast on every read — one wrong cast blew up at runtime. Generics move that check to compile time, so the whole class of ClassCastException bugs disappears.

Quick Quiz

1. Java arrays are…
2. Why is List<int> illegal?
3. scores.getOrDefault("x", 0) on a missing key returns…
4. A HashSet guarantees…
5. Generics move type checking to…