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 primitives — List<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…