Lesson 9 / 11

Generics and Collections Framework

Generics let a class or method work with any type while the compiler still checks type-safety at compile time — this is exactly what powers ArrayList and every other collection type you’ve already used in this course.

public class Box<T> {
    private T contents;

    public void set(T contents) {
        this.contents = contents;
    }

    public T get() {
        return contents;
    }
}

Box<String> stringBox = new Box<>();
stringBox.set("Java");
String value = stringBox.get();   // no cast needed -- the compiler already knows it's a String

T is a placeholder type parameter — by convention a single capital letter, though the name itself is arbitrary. Before generics existed (prior to Java 5), code like this had to use the generic Object type and manually cast values back to their real type everywhere, which was both verbose and unsafe.

Beyond ArrayList: the Collections Framework

import java.util.*;

Map<String, Integer> scores = new HashMap<>();
scores.put("Yash", 95);
scores.put("Ana", 88);
System.out.println(scores.get("Yash"));   // 95

Set<String> uniqueCourses = new HashSet<>();
uniqueCourses.add("Java");
uniqueCourses.add("Java");   // ignored -- sets don't allow duplicates
System.out.println(uniqueCourses.size());   // 1

Use a Map for key-value lookups, a Set when duplicates should be impossible by design, and List (like ArrayList) when order and duplicates both matter. Recognizing which of these shapes fits your data is one of the most valuable everyday skills in Java, and it mirrors the same decision you’d make choosing between a Python list, set, and dict.

Bounded type parameters

public static double sumOfList(List<? extends Number> numbers) {
    double sum = 0;
    for (Number n : numbers) {
        sum += n.doubleValue();
    }
    return sum;
}

? extends Number is a wildcard restricting the generic type to Number or any of its subclasses (Integer, Double, and so on) — this lets one method safely accept a list of any numeric type, rather than writing a separate overload for each one.