Home › Learn › Java › Interfaces, generics, and streams

Generics

Lesson 34 of 40. Classes and methods that work for any type.

List<String> is a generic class used with a type argument, and you can write your own: class Box<T> { T value; T get() { return value; } } works for any T, and Box<Integer> or Box<String> picks it. The point is that the compiler checks the types: a Box<String> cannot hold a number, and get() returns a String without a cast.

Methods can be generic too: static <T> T last(List<T> xs) returns whatever the list holds. A bound restricts the type: <T extends Comparable<T>> means "any T that can be compared to itself", which is what a generic largest needs to call compareTo.

class Box<T> {
    T value;

    Box(T value) {
        this.value = value;
    }

    T get() {
        return value;
    }
}

static <T> T last(List<T> xs) {
    return xs.get(xs.size() - 1);
}

Your task

Write class Pair<A, B> holding two values, with a constructor Pair(A first, B second), accessors first() and second(), and Pair<B, A> swapped(). Then write two generic methods in Main: static <T> T last(List<T> xs) (assume the list is not empty) and static <T extends Comparable<T>> T largest(List<T> xs) returning the largest by compareTo.

Hint 1

class Pair<A, B> { A first; B second; Pair(A first, B second) { ... } A first() { return first; } B second() { return second; } Pair<B, A> swapped() { return new Pair<>(second, first); } }

Hint 2

largest: T best = xs.get(0); for (T x : xs) if (x.compareTo(best) > 0) best = x; return best;

Show the solution
import java.util.*;

public class Main {
    static <T> T last(List<T> xs) {
        return xs.get(xs.size() - 1);
    }

    static <T extends Comparable<T>> T largest(List<T> xs) {
        T best = xs.get(0);
        for (T x : xs) {
            if (x.compareTo(best) > 0) {
                best = x;
            }
        }
        return best;
    }

    public static void main(String[] args) {
        Pair<String, Integer> p = new Pair<>("age", 36);
        System.out.println(p.swapped().first() + " " + largest(List.of(3, 9, 4)));
    }
}

class Pair<A, B> {
    private A first;
    private B second;

    Pair(A first, B second) {
        this.first = first;
        this.second = second;
    }

    A first() {
        return first;
    }

    B second() {
        return second;
    }

    Pair<B, A> swapped() {
        return new Pair<>(second, first);
    }
}

    Compiles with OpenJDK javac and TeaVM, both compiled to WebAssembly (7 MB download the first time, then cached), and runs in this tab; nothing is sent anywhere.