Your utility class needs a swap method that works with any type. You don't want a generic class - just one method. Generic methods declare their own type parameters, independent of any class generics.

Basic generic method

Declare type parameter before return type.

searchNumber
Basic.java
Replay: real traced execution (multi-file project)
import java.util.*;

public class Basic {
    public static <T> void print(T item) {
        System.out.println("  Item: " + item);
    }

    public static <T> void printArray(T[] array) {
        System.out.print("  Array: [");
        for (int i = 0; i < array.length; i++) {
            if (i > 0) System.out.print(", ");
            System.out.print(array[i]);
        }
        System.out.println("]");
    }

    public static void main(String[] args) {
        System.out.println("Basic generic methods:\n");

        print(42);
        print("Hello");
        print(3.14);

        Integer[] ints = {1, 2, 3, 4, 5};
        String[] strs = {"a", "b", "c"};

        printArray(ints);
        printArray(strs);

        // Generic methods have type parameters: <T>
        // Type parameter comes before return type
        // Can be used in parameters and return type
        // Java infers type from arguments

        System.out.println("\nIdentity function:");

        class Utils {
            public static <T> T identity(T value) {
                return value;
            }
        }

        Integer num = Utils.identity(42);
        String text = Utils.identity("Hello");

        System.out.println("  Number: " + num);
        System.out.println("  Text: " + text);

        System.out.println("\nSwap elements:");

        class ArrayOps {
            public static <T> void swap(T[] array, int i, int j) {
                T temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }

        Integer[] numbers = {1, 2, 3, 4, 5};
        System.out.println("  Before: " + Arrays.toString(numbers));
        ArrayOps.swap(numbers, 0, 4);
        System.out.println("  After: " + Arrays.toString(numbers));

        System.out.println("\nGet first:");

        class Getter {
            public static <T> T getFirst(T[] array) {
                return array.length > 0 ? array[0] : null;
            }

            public static <T> T getFirst(List<T> list) {
                return list.isEmpty() ? null : list.get(0);
            }
        }

        System.out.println("  First int: " + Getter.getFirst(ints));
        System.out.println("  First string: " + Getter.getFirst(strs));

        System.out.println("\nCreate pair:");

        class Pair<K, V> {
            K key;
            V value;

            Pair(K key, V value) {
                this.key = key;
                this.value = value;
            }

            public String toString() {
                return "(" + key + ", " + value + ")";
            }
        }

        class PairFactory {
            public static <K, V> Pair<K, V> create(K key, V value) {
                return new Pair<>(key, value);
            }
        }

        Pair<String, Integer> p1 = PairFactory.create("age", 30);
        Pair<Integer, String> p2 = PairFactory.create(1, "first");

        System.out.println("  Pair 1: " + p1);
        System.out.println("  Pair 2: " + p2);

        System.out.println("\nContains check:");

        class Checker {
            public static <T> boolean contains(T[] array, T item) {
                for (T element : array) {
                    if (element.equals(item)) {
                        return true;
                    }
                }
                return false;
            }
        }

        int searchNumber = 3;
        System.out.println("  ints contains " + searchNumber + ": " +
                         Checker.contains(ints, searchNumber));
        System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));
    }
}
import java.util.*;

public class Basic {
    public static <T> void print(T item) {
        System.out.println("  Item: " + item);
    }

    public static <T> void printArray(T[] array) {
        System.out.print("  Array: [");
        for (int i = 0; i < array.length; i++) {
            if (i > 0) System.out.print(", ");
            System.out.print(array[i]);
        }
        System.out.println("]");
    }

    public static void main(String[] args) {
        System.out.println("Basic generic methods:\n");

        print(42);
        print("Hello");
        print(3.14);

        Integer[] ints = {1, 2, 3, 4, 5};
        String[] strs = {"a", "b", "c"};

        printArray(ints);
        printArray(strs);

        // Generic methods have type parameters: <T>
        // Type parameter comes before return type
        // Can be used in parameters and return type
        // Java infers type from arguments

        System.out.println("\nIdentity function:");

        class Utils {
            public static <T> T identity(T value) {
                return value;
            }
        }

        Integer num = Utils.identity(42);
        String text = Utils.identity("Hello");

        System.out.println("  Number: " + num);
        System.out.println("  Text: " + text);

        System.out.println("\nSwap elements:");

        class ArrayOps {
            public static <T> void swap(T[] array, int i, int j) {
                T temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }

        Integer[] numbers = {1, 2, 3, 4, 5};
        System.out.println("  Before: " + Arrays.toString(numbers));
        ArrayOps.swap(numbers, 0, 4);
        System.out.println("  After: " + Arrays.toString(numbers));

        System.out.println("\nGet first:");

        class Getter {
            public static <T> T getFirst(T[] array) {
                return array.length > 0 ? array[0] : null;
            }

            public static <T> T getFirst(List<T> list) {
                return list.isEmpty() ? null : list.get(0);
            }
        }

        System.out.println("  First int: " + Getter.getFirst(ints));
        System.out.println("  First string: " + Getter.getFirst(strs));

        System.out.println("\nCreate pair:");

        class Pair<K, V> {
            K key;
            V value;

            Pair(K key, V value) {
                this.key = key;
                this.value = value;
            }

            public String toString() {
                return "(" + key + ", " + value + ")";
            }
        }

        class PairFactory {
            public static <K, V> Pair<K, V> create(K key, V value) {
                return new Pair<>(key, value);
            }
        }

        Pair<String, Integer> p1 = PairFactory.create("age", 30);
        Pair<Integer, String> p2 = PairFactory.create(1, "first");

        System.out.println("  Pair 1: " + p1);
        System.out.println("  Pair 2: " + p2);

        System.out.println("\nContains check:");

        class Checker {
            public static <T> boolean contains(T[] array, T item) {
                for (T element : array) {
                    if (element.equals(item)) {
                        return true;
                    }
                }
                return false;
            }
        }

        int searchNumber = 1;
        System.out.println("  ints contains " + searchNumber + ": " +
                         Checker.contains(ints, searchNumber));
        System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));
    }
}
import java.util.*;

public class Basic {
    public static <T> void print(T item) {
        System.out.println("  Item: " + item);
    }

    public static <T> void printArray(T[] array) {
        System.out.print("  Array: [");
        for (int i = 0; i < array.length; i++) {
            if (i > 0) System.out.print(", ");
            System.out.print(array[i]);
        }
        System.out.println("]");
    }

    public static void main(String[] args) {
        System.out.println("Basic generic methods:\n");

        print(42);
        print("Hello");
        print(3.14);

        Integer[] ints = {1, 2, 3, 4, 5};
        String[] strs = {"a", "b", "c"};

        printArray(ints);
        printArray(strs);

        // Generic methods have type parameters: <T>
        // Type parameter comes before return type
        // Can be used in parameters and return type
        // Java infers type from arguments

        System.out.println("\nIdentity function:");

        class Utils {
            public static <T> T identity(T value) {
                return value;
            }
        }

        Integer num = Utils.identity(42);
        String text = Utils.identity("Hello");

        System.out.println("  Number: " + num);
        System.out.println("  Text: " + text);

        System.out.println("\nSwap elements:");

        class ArrayOps {
            public static <T> void swap(T[] array, int i, int j) {
                T temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }

        Integer[] numbers = {1, 2, 3, 4, 5};
        System.out.println("  Before: " + Arrays.toString(numbers));
        ArrayOps.swap(numbers, 0, 4);
        System.out.println("  After: " + Arrays.toString(numbers));

        System.out.println("\nGet first:");

        class Getter {
            public static <T> T getFirst(T[] array) {
                return array.length > 0 ? array[0] : null;
            }

            public static <T> T getFirst(List<T> list) {
                return list.isEmpty() ? null : list.get(0);
            }
        }

        System.out.println("  First int: " + Getter.getFirst(ints));
        System.out.println("  First string: " + Getter.getFirst(strs));

        System.out.println("\nCreate pair:");

        class Pair<K, V> {
            K key;
            V value;

            Pair(K key, V value) {
                this.key = key;
                this.value = value;
            }

            public String toString() {
                return "(" + key + ", " + value + ")";
            }
        }

        class PairFactory {
            public static <K, V> Pair<K, V> create(K key, V value) {
                return new Pair<>(key, value);
            }
        }

        Pair<String, Integer> p1 = PairFactory.create("age", 30);
        Pair<Integer, String> p2 = PairFactory.create(1, "first");

        System.out.println("  Pair 1: " + p1);
        System.out.println("  Pair 2: " + p2);

        System.out.println("\nContains check:");

        class Checker {
            public static <T> boolean contains(T[] array, T item) {
                for (T element : array) {
                    if (element.equals(item)) {
                        return true;
                    }
                }
                return false;
            }
        }

        int searchNumber = 6;
        System.out.println("  ints contains " + searchNumber + ": " +
                         Checker.contains(ints, searchNumber));
        System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));
    }
}
  1. public static void main(String[] args)

    17public static void main(String[] args) {18    System.out.println("Basic generic methods:\n");
    outputBasic generic methods:
    Basic generic methods:
  2. public static <T> void print(T item)

    pass 1 of 3
    3public class Basic {4    public static <T> void print(T item42) {5        System.out.println("  Item: " + item42);6    }
    output  Item: 42
    All 3 passes — pass 1 is the card above
    passitem
    142
    2Hello
    33.14
  3. public static <T> void printArray(T[] array)

    pass 1 of 2
    8public static <T> void printArray(T[] array) {9    System.out.print("  Array: [");10    for (int i = 0; i < array.length; i++) {
    output  Array: [
  4. for (int i = 0; i < array.length; i++)

    pass 1 of 8
    9System.out.print("  Array: [");10for (int i0 = 0; i < array.length5; i++) {11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]1);13}
    output1
    All 8 passes — pass 1 is the card above
    passiarray.lengtharray[i]
    1051
    215
    325
    435
    545
    603a
    713
    823
  5. if (i > 0)

    pass 1 of 6
    10for (int i = 0; i < array.length; i++) {11    if (i1 > 0) System.out.print(", ");12    System.out.print(array[i]);
    output, 
    All 6 passes — pass 1 is the card above
    passi
    11
    22
    33
    44
    51
    62
  6. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]2);13}
    output2
    values this step1i
  7. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]3);13}
    output3
    values this step2i
  8. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]4);13}
    output4
    values this step3i
  9. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]5);13}
    output5
    values this step4i
  10. System.out.println("]");

    13    }14    System.out.println("]");15}
    output]
  11. public static <T> void printArray(T[] array)

    pass 2 of 2
    8public static <T> void printArray(T[] array) {9    System.out.print("  Array: [");10    for (int i = 0; i < array.length; i++) {
    output  Array: [
  12. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]b);13}
    outputb
    values this step1i
  13. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]c);13}
    outputc
    values this step2i
  14. System.out.println("]");

    13    }14    System.out.println("]");15}
    output]
  15. System.out.println(" Identity function:");

    35System.out.println("\nIdentity function:");
    output
    Identity function:
    
    Identity function:
  16. public static <T> T identity(T value)

    pass 1 of 2
    37class Utils {38    public static <T> T identity(T value42) {39        return value42;40    }
  17. public static <T> T identity(T value)

    pass 2 of 2
    37class Utils {38    public static <T> T identity(T valueHello) {39        return valueHello;40    }
  18. System.out.println(" Number: " + num);

    46System.out.println("  Number: " + num42);47System.out.println("  Text: " + textHello);4849System.out.println("\nSwap elements:");5051class ArrayOps {52    public static <T> void swap(T[] array, int i, int j) {53        T temp = array[i];54        array[i] = array[j];55        array[j] = temp;56    }57}5859Integer[] numbers = {1, 2, 3, 4, 5};60System.out.println("  Before: " + Arrays.toString(numbers));61ArrayOps.swap(numbers, 0, 4);
    output  Number: 42
      Number: 42
      Text: Hello
      Text: Hello
    
    Swap elements:
    
    Swap elements:
      Before: [1, 2, 3, 4, 5]
      Before: [1, 2, 3, 4, 5]
  19. temp ← 1, array[i] ← 5, array[j] ← 1

    51class ArrayOps {52    public static <T> void swap(T[] array, int i0, int j4) {53        T temp→ 1 = array[i]1;54        array[i]→ 5 = array[j]5;55        array[j]→ 1 = temp1;56    }
  20. System.out.println(" After: " + Arrays.toString(numbers));

    61ArrayOps.swap(numbers, 0, 4);62System.out.println("  After: " + Arrays.toString(numbers));6364System.out.println("\nGet first:");
    output  After: [5, 2, 3, 4, 1]
      After: [5, 2, 3, 4, 1]
    
    Get first:
    
    Get first:
  21. public static <T> T getFirst(T[] array)

    pass 1 of 3
    66class Getter {67    public static <T> T getFirst(T[] array) {68        return array.length5 > 0 ? array[0]1 : null;69    }
    All 3 passes — pass 1 is the card above
    passarray.lengtharray[0]
    151
    23a
    33a
  22. System.out.println(" First string: " + Getter.getFirst(strs));

    76System.out.println("  First int: " + Getter.getFirst(ints));77System.out.println("  First string: " + Getter.getFirst(strs));
  23. System.out.println(" First string: " + Getter.getFirst(strs));

    76System.out.println("  First int: " + Getter.getFirst(ints));77System.out.println("  First string: " + Getter.getFirst(strs));
    output  First string: a
  24. System.out.println(" First string: " + Getter.getFirst(strs));

    76System.out.println("  First int: " + Getter.getFirst(ints));77System.out.println("  First string: " + Getter.getFirst(strs));7879System.out.println("\nCreate pair:");
    output  First string: a
    
    Create pair:
    
    Create pair:
  25. public static <K, V> Pair<K, V> create(K key, V value)

    pass 1 of 2
    95class PairFactory {96    public static <K, V> Pair<K, V> create(K keyage, V value30) {97        return new Pair<>(key, value);98    }
  26. this.key ← age, this.value ← 30

    pass 1 of 2
    85Pair(K keyage, V value30) {86    this.key→ age = keyage;87    this.value→ 30 = value30;88}
  27. public static <K, V> Pair<K, V> create(K key, V value)

    pass 2 of 2
    95class PairFactory {96    public static <K, V> Pair<K, V> create(K key1, V valuefirst) {97        return new Pair<>(key, value);98    }
  28. this.key ← 1, this.value ← first

    pass 2 of 2
    85Pair(K key1, V valuefirst) {86    this.key→ 1 = key1;87    this.value→ first = valuefirst;88}
  29. System.out.println(" Pair 1: " + p1);

    104System.out.println("  Pair 1: " + p1(age, 30));105System.out.println("  Pair 2: " + p2(1, first));106107System.out.println("\nContains check:");108109class Checker {110    public static <T> boolean contains(T[] array, T item) {111        for (T element : array) {112            if (element.equals(item)) {113                return true;114            }115        }116        return false;117    }118}119120int searchNumber = 3; //@searchNumber=3, 1, 6121System.out.println("  ints contains " + searchNumber3 + ": " +122                 Checker.contains(ints, searchNumber3));123System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));
    output  Pair 1: (age, 30)
      Pair 1: (age, 30)
      Pair 2: (1, first)
      Pair 2: (1, first)
    
    Contains check:
    
    Contains check:
  30. public static <T> boolean contains(T[] array, T item)

    pass 1 of 2
    109class Checker {110    public static <T> boolean contains(T[] array, T item3) {111        for (T element : array) {
  31. for (T element : array)

    pass 1 of 6
    110public static <T> boolean contains(T[] array, T item) {111    for (T element1 : array) {112        if (element.equals(item)) {
    All 6 passes — pass 1 is the card above
    passelementitem
    11
    22
    333
    4a
    5b
    6c
  32. if (element.equals(item))

    111for (T element : array) {112    if (element.equals(item3)) {113        return true;114    }
  33. System.out.println(" ints contains " + searchNumber + ": " +

    120    int searchNumber = 3; //@searchNumber=3, 1, 6121    System.out.println("  ints contains " + searchNumber3 + ": " +122                     Checker.contains(ints, searchNumber3));123    System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));124}
    output  ints contains 3: true
  34. public static <T> boolean contains(T[] array, T item)

    pass 2 of 2
    109class Checker {110    public static <T> boolean contains(T[] array, T itemd) {111        for (T element : array) {
  35. return false;

    115    }116    return false;117}
  36. System.out.println(" strs contains 'd': " + Checker.contains(strs, "d…

    122                     Checker.contains(ints, searchNumber));123    System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));124}
    output  strs contains 'd': false
  1. public static void main(String[] args)

    17public static void main(String[] args) {18    System.out.println("Basic generic methods:\n");
    outputBasic generic methods:
    Basic generic methods:
  2. public static <T> void print(T item)

    pass 1 of 3
    3public class Basic {4    public static <T> void print(T item42) {5        System.out.println("  Item: " + item42);6    }
    output  Item: 42
    All 3 passes — pass 1 is the card above
    passitem
    142
    2Hello
    33.14
  3. public static <T> void printArray(T[] array)

    pass 1 of 2
    8public static <T> void printArray(T[] array) {9    System.out.print("  Array: [");10    for (int i = 0; i < array.length; i++) {
    output  Array: [
  4. for (int i = 0; i < array.length; i++)

    pass 1 of 8
    9System.out.print("  Array: [");10for (int i0 = 0; i < array.length5; i++) {11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]1);13}
    output1
    All 8 passes — pass 1 is the card above
    passiarray.lengtharray[i]
    1051
    215
    325
    435
    545
    603a
    713
    823
  5. if (i > 0)

    pass 1 of 6
    10for (int i = 0; i < array.length; i++) {11    if (i1 > 0) System.out.print(", ");12    System.out.print(array[i]);
    output, 
    All 6 passes — pass 1 is the card above
    passi
    11
    22
    33
    44
    51
    62
  6. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]2);13}
    output2
    values this step1i
  7. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]3);13}
    output3
    values this step2i
  8. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]4);13}
    output4
    values this step3i
  9. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]5);13}
    output5
    values this step4i
  10. System.out.println("]");

    13    }14    System.out.println("]");15}
    output]
  11. public static <T> void printArray(T[] array)

    pass 2 of 2
    8public static <T> void printArray(T[] array) {9    System.out.print("  Array: [");10    for (int i = 0; i < array.length; i++) {
    output  Array: [
  12. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]b);13}
    outputb
    values this step1i
  13. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]c);13}
    outputc
    values this step2i
  14. System.out.println("]");

    13    }14    System.out.println("]");15}
    output]
  15. System.out.println(" Identity function:");

    35System.out.println("\nIdentity function:");
    output
    Identity function:
    
    Identity function:
  16. public static <T> T identity(T value)

    pass 1 of 2
    37class Utils {38    public static <T> T identity(T value42) {39        return value42;40    }
  17. public static <T> T identity(T value)

    pass 2 of 2
    37class Utils {38    public static <T> T identity(T valueHello) {39        return valueHello;40    }
  18. System.out.println(" Number: " + num);

    46System.out.println("  Number: " + num42);47System.out.println("  Text: " + textHello);4849System.out.println("\nSwap elements:");5051class ArrayOps {52    public static <T> void swap(T[] array, int i, int j) {53        T temp = array[i];54        array[i] = array[j];55        array[j] = temp;56    }57}5859Integer[] numbers = {1, 2, 3, 4, 5};60System.out.println("  Before: " + Arrays.toString(numbers));61ArrayOps.swap(numbers, 0, 4);
    output  Number: 42
      Number: 42
      Text: Hello
      Text: Hello
    
    Swap elements:
    
    Swap elements:
      Before: [1, 2, 3, 4, 5]
      Before: [1, 2, 3, 4, 5]
  19. temp ← 1, array[i] ← 5, array[j] ← 1

    51class ArrayOps {52    public static <T> void swap(T[] array, int i0, int j4) {53        T temp→ 1 = array[i]1;54        array[i]→ 5 = array[j]5;55        array[j]→ 1 = temp1;56    }
  20. System.out.println(" After: " + Arrays.toString(numbers));

    61ArrayOps.swap(numbers, 0, 4);62System.out.println("  After: " + Arrays.toString(numbers));6364System.out.println("\nGet first:");
    output  After: [5, 2, 3, 4, 1]
      After: [5, 2, 3, 4, 1]
    
    Get first:
    
    Get first:
  21. public static <T> T getFirst(T[] array)

    pass 1 of 3
    66class Getter {67    public static <T> T getFirst(T[] array) {68        return array.length5 > 0 ? array[0]1 : null;69    }
    All 3 passes — pass 1 is the card above
    passarray.lengtharray[0]
    151
    23a
    33a
  22. System.out.println(" First string: " + Getter.getFirst(strs));

    76System.out.println("  First int: " + Getter.getFirst(ints));77System.out.println("  First string: " + Getter.getFirst(strs));
  23. System.out.println(" First string: " + Getter.getFirst(strs));

    76System.out.println("  First int: " + Getter.getFirst(ints));77System.out.println("  First string: " + Getter.getFirst(strs));
    output  First string: a
  24. System.out.println(" First string: " + Getter.getFirst(strs));

    76System.out.println("  First int: " + Getter.getFirst(ints));77System.out.println("  First string: " + Getter.getFirst(strs));7879System.out.println("\nCreate pair:");
    output  First string: a
    
    Create pair:
    
    Create pair:
  25. public static <K, V> Pair<K, V> create(K key, V value)

    pass 1 of 2
    95class PairFactory {96    public static <K, V> Pair<K, V> create(K keyage, V value30) {97        return new Pair<>(key, value);98    }
  26. this.key ← age, this.value ← 30

    pass 1 of 2
    85Pair(K keyage, V value30) {86    this.key→ age = keyage;87    this.value→ 30 = value30;88}
  27. public static <K, V> Pair<K, V> create(K key, V value)

    pass 2 of 2
    95class PairFactory {96    public static <K, V> Pair<K, V> create(K key1, V valuefirst) {97        return new Pair<>(key, value);98    }
  28. this.key ← 1, this.value ← first

    pass 2 of 2
    85Pair(K key1, V valuefirst) {86    this.key→ 1 = key1;87    this.value→ first = valuefirst;88}
  29. System.out.println(" Pair 1: " + p1);

    104System.out.println("  Pair 1: " + p1(age, 30));105System.out.println("  Pair 2: " + p2(1, first));106107System.out.println("\nContains check:");108109class Checker {110    public static <T> boolean contains(T[] array, T item) {111        for (T element : array) {112            if (element.equals(item)) {113                return true;114            }115        }116        return false;117    }118}119120int searchNumber = 1;121System.out.println("  ints contains " + searchNumber1 + ": " +122                 Checker.contains(ints, searchNumber1));123System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));
    output  Pair 1: (age, 30)
      Pair 1: (age, 30)
      Pair 2: (1, first)
      Pair 2: (1, first)
    
    Contains check:
    
    Contains check:
  30. public static <T> boolean contains(T[] array, T item)

    pass 1 of 2
    109class Checker {110    public static <T> boolean contains(T[] array, T item1) {111        for (T element : array) {
  31. for (T element : array)

    pass 1 of 4
    110public static <T> boolean contains(T[] array, T item) {111    for (T element1 : array) {112        if (element.equals(item)) {
    All 4 passes — pass 1 is the card above
    passelementitem
    111
    2a
    3b
    4c
  32. if (element.equals(item))

    111for (T element : array) {112    if (element.equals(item1)) {113        return true;114    }
  33. System.out.println(" ints contains " + searchNumber + ": " +

    120    int searchNumber = 1;121    System.out.println("  ints contains " + searchNumber1 + ": " +122                     Checker.contains(ints, searchNumber1));123    System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));124}
    output  ints contains 1: true
  34. public static <T> boolean contains(T[] array, T item)

    pass 2 of 2
    109class Checker {110    public static <T> boolean contains(T[] array, T itemd) {111        for (T element : array) {
  35. return false;

    115    }116    return false;117}
  36. System.out.println(" strs contains 'd': " + Checker.contains(strs, "d…

    122                     Checker.contains(ints, searchNumber));123    System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));124}
    output  strs contains 'd': false
  1. public static void main(String[] args)

    17public static void main(String[] args) {18    System.out.println("Basic generic methods:\n");
    outputBasic generic methods:
    Basic generic methods:
  2. public static <T> void print(T item)

    pass 1 of 3
    3public class Basic {4    public static <T> void print(T item42) {5        System.out.println("  Item: " + item42);6    }
    output  Item: 42
    All 3 passes — pass 1 is the card above
    passitem
    142
    2Hello
    33.14
  3. public static <T> void printArray(T[] array)

    pass 1 of 2
    8public static <T> void printArray(T[] array) {9    System.out.print("  Array: [");10    for (int i = 0; i < array.length; i++) {
    output  Array: [
  4. for (int i = 0; i < array.length; i++)

    pass 1 of 8
    9System.out.print("  Array: [");10for (int i0 = 0; i < array.length5; i++) {11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]1);13}
    output1
    All 8 passes — pass 1 is the card above
    passiarray.lengtharray[i]
    1051
    215
    325
    435
    545
    603a
    713
    823
  5. if (i > 0)

    pass 1 of 6
    10for (int i = 0; i < array.length; i++) {11    if (i1 > 0) System.out.print(", ");12    System.out.print(array[i]);
    output, 
    All 6 passes — pass 1 is the card above
    passi
    11
    22
    33
    44
    51
    62
  6. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]2);13}
    output2
    values this step1i
  7. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]3);13}
    output3
    values this step2i
  8. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]4);13}
    output4
    values this step3i
  9. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]5);13}
    output5
    values this step4i
  10. System.out.println("]");

    13    }14    System.out.println("]");15}
    output]
  11. public static <T> void printArray(T[] array)

    pass 2 of 2
    8public static <T> void printArray(T[] array) {9    System.out.print("  Array: [");10    for (int i = 0; i < array.length; i++) {
    output  Array: [
  12. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]b);13}
    outputb
    values this step1i
  13. System.out.print(array[i]);

    11    if (i > 0) System.out.print(", ");12    System.out.print(array[i]c);13}
    outputc
    values this step2i
  14. System.out.println("]");

    13    }14    System.out.println("]");15}
    output]
  15. System.out.println(" Identity function:");

    35System.out.println("\nIdentity function:");
    output
    Identity function:
    
    Identity function:
  16. public static <T> T identity(T value)

    pass 1 of 2
    37class Utils {38    public static <T> T identity(T value42) {39        return value42;40    }
  17. public static <T> T identity(T value)

    pass 2 of 2
    37class Utils {38    public static <T> T identity(T valueHello) {39        return valueHello;40    }
  18. System.out.println(" Number: " + num);

    46System.out.println("  Number: " + num42);47System.out.println("  Text: " + textHello);4849System.out.println("\nSwap elements:");5051class ArrayOps {52    public static <T> void swap(T[] array, int i, int j) {53        T temp = array[i];54        array[i] = array[j];55        array[j] = temp;56    }57}5859Integer[] numbers = {1, 2, 3, 4, 5};60System.out.println("  Before: " + Arrays.toString(numbers));61ArrayOps.swap(numbers, 0, 4);
    output  Number: 42
      Number: 42
      Text: Hello
      Text: Hello
    
    Swap elements:
    
    Swap elements:
      Before: [1, 2, 3, 4, 5]
      Before: [1, 2, 3, 4, 5]
  19. temp ← 1, array[i] ← 5, array[j] ← 1

    51class ArrayOps {52    public static <T> void swap(T[] array, int i0, int j4) {53        T temp→ 1 = array[i]1;54        array[i]→ 5 = array[j]5;55        array[j]→ 1 = temp1;56    }
  20. System.out.println(" After: " + Arrays.toString(numbers));

    61ArrayOps.swap(numbers, 0, 4);62System.out.println("  After: " + Arrays.toString(numbers));6364System.out.println("\nGet first:");
    output  After: [5, 2, 3, 4, 1]
      After: [5, 2, 3, 4, 1]
    
    Get first:
    
    Get first:
  21. public static <T> T getFirst(T[] array)

    pass 1 of 3
    66class Getter {67    public static <T> T getFirst(T[] array) {68        return array.length5 > 0 ? array[0]1 : null;69    }
    All 3 passes — pass 1 is the card above
    passarray.lengtharray[0]
    151
    23a
    33a
  22. System.out.println(" First string: " + Getter.getFirst(strs));

    76System.out.println("  First int: " + Getter.getFirst(ints));77System.out.println("  First string: " + Getter.getFirst(strs));
  23. System.out.println(" First string: " + Getter.getFirst(strs));

    76System.out.println("  First int: " + Getter.getFirst(ints));77System.out.println("  First string: " + Getter.getFirst(strs));
    output  First string: a
  24. System.out.println(" First string: " + Getter.getFirst(strs));

    76System.out.println("  First int: " + Getter.getFirst(ints));77System.out.println("  First string: " + Getter.getFirst(strs));7879System.out.println("\nCreate pair:");
    output  First string: a
    
    Create pair:
    
    Create pair:
  25. public static <K, V> Pair<K, V> create(K key, V value)

    pass 1 of 2
    95class PairFactory {96    public static <K, V> Pair<K, V> create(K keyage, V value30) {97        return new Pair<>(key, value);98    }
  26. this.key ← age, this.value ← 30

    pass 1 of 2
    85Pair(K keyage, V value30) {86    this.key→ age = keyage;87    this.value→ 30 = value30;88}
  27. public static <K, V> Pair<K, V> create(K key, V value)

    pass 2 of 2
    95class PairFactory {96    public static <K, V> Pair<K, V> create(K key1, V valuefirst) {97        return new Pair<>(key, value);98    }
  28. this.key ← 1, this.value ← first

    pass 2 of 2
    85Pair(K key1, V valuefirst) {86    this.key→ 1 = key1;87    this.value→ first = valuefirst;88}
  29. System.out.println(" Pair 1: " + p1);

    104System.out.println("  Pair 1: " + p1(age, 30));105System.out.println("  Pair 2: " + p2(1, first));106107System.out.println("\nContains check:");108109class Checker {110    public static <T> boolean contains(T[] array, T item) {111        for (T element : array) {112            if (element.equals(item)) {113                return true;114            }115        }116        return false;117    }118}119120int searchNumber = 6;121System.out.println("  ints contains " + searchNumber6 + ": " +122                 Checker.contains(ints, searchNumber6));123System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));
    output  Pair 1: (age, 30)
      Pair 1: (age, 30)
      Pair 2: (1, first)
      Pair 2: (1, first)
    
    Contains check:
    
    Contains check:
  30. public static <T> boolean contains(T[] array, T item)

    pass 1 of 2
    109class Checker {110    public static <T> boolean contains(T[] array, T item6) {111        for (T element : array) {
  31. for (T element : array)

    pass 1 of 8
    110public static <T> boolean contains(T[] array, T item) {111    for (T element1 : array) {112        if (element.equals(item)) {
    All 8 passes — pass 1 is the card above
    passelement
    11
    22
    33
    44
    55
    6a
    7b
    8c
  32. return false;

    115    }116    return false;117}
  33. System.out.println(" ints contains " + searchNumber + ": " +

    120    int searchNumber = 6;121    System.out.println("  ints contains " + searchNumber6 + ": " +122                     Checker.contains(ints, searchNumber6));123    System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));124}
    output  ints contains 6: false
  34. public static <T> boolean contains(T[] array, T item)

    pass 2 of 2
    109class Checker {110    public static <T> boolean contains(T[] array, T itemd) {111        for (T element : array) {
  35. return false;

    115    }116    return false;117}
  36. System.out.println(" strs contains 'd': " + Checker.contains(strs, "d…

    122                     Checker.contains(ints, searchNumber));123    System.out.println("  strs contains 'd': " + Checker.contains(strs, "d"));124}
    output  strs contains 'd': false

<T> T method(T arg) - T is scoped to this method only.

generic method Method with its own type parameter: `<T> void process(T item)`.

Bounded generic methods

Restrict type parameter to certain types.

countThreshold
Bounds.java
Replay: real traced execution (multi-file project)
import java.util.*;

public class Bounds {
    public static <T extends Comparable<T>> T max(T a, T b) {
        return a.compareTo(b) > 0 ? a : b;
    }

    public static <T extends Comparable<T>> T min(T a, T b) {
        return a.compareTo(b) < 0 ? a : b;
    }

    public static void main(String[] args) {
        System.out.println("Bounded generic methods:\n");

        System.out.println("  max(5, 10): " + max(5, 10));
        System.out.println("  max('a', 'z'): " + max('a', 'z'));
        System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));

        // <T extends Type> constrains T to be Type or subclass
        // Allows calling Type's methods on T
        // Common with Comparable, Number, Serializable
        // Can combine multiple bounds with &

        System.out.println("\nSum numbers:");

        class NumberOps {
            public static <T extends Number> double sum(T[] numbers) {
                double total = 0;
                for (T num : numbers) {
                    total += num.doubleValue();
                }
                return total;
            }

            public static <T extends Number> double average(T[] numbers) {
                if (numbers.length == 0) {
                    return 0;
                }
                return sum(numbers) / numbers.length;
            }
        }

        Integer[] ints = {1, 2, 3, 4, 5};
        Double[] doubles = {1.5, 2.5, 3.5};

        System.out.println("  Sum ints: " + NumberOps.sum(ints));
        System.out.println("  Sum doubles: " + NumberOps.sum(doubles));
        System.out.println("  Average: " + NumberOps.average(ints));

        System.out.println("\nFind maximum:");

        class Finder {
            public static <T extends Comparable<T>> T findMax(T[] array) {
                if (array.length == 0) {
                    return null;
                }

                T max = array[0];
                for (T item : array) {
                    if (item.compareTo(max) > 0) {
                        max = item;
                    }
                }
                return max;
            }
        }

        System.out.println("  Max int: " + Finder.findMax(ints));

        String[] words = {"apple", "zebra", "banana", "cherry"};
        System.out.println("  Max string: " + Finder.findMax(words));

        System.out.println("\nSort array:");

        class Sorter {
            public static <T extends Comparable<T>> void sort(T[] array) {
                for (int i = 0; i < array.length - 1; i++) {
                    for (int j = i + 1; j < array.length; j++) {
                        if (array[i].compareTo(array[j]) > 0) {
                            T temp = array[i];
                            array[i] = array[j];
                            array[j] = temp;
                        }
                    }
                }
            }
        }

        Integer[] nums = {5, 2, 8, 1, 9};
        System.out.println("  Before: " + Arrays.toString(nums));
        Sorter.sort(nums);
        System.out.println("  After: " + Arrays.toString(nums));

        System.out.println("\nClamp value:");

        class RangeOps {
            public static <T extends Comparable<T>> T clamp(
                    T value, T min, T max) {
                if (value.compareTo(min) < 0) {
                    return min;
                }
                if (value.compareTo(max) > 0) {
                    return max;
                }
                return value;
            }
        }

        System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));
        System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));
        System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));

        System.out.println("\nCount greater:");

        class Counter {
            public static <T extends Comparable<T>> int countGreater(
                    T[] array, T threshold) {
                int count = 0;
                for (T item : array) {
                    if (item.compareTo(threshold) > 0) {
                        count++;
                    }
                }
                return count;
            }
        }

        int countThreshold = 3;
        System.out.println("  Count > " + countThreshold + ": " +
                         Counter.countGreater(ints, countThreshold));
        System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));
    }
}
import java.util.*;

public class Bounds {
    public static <T extends Comparable<T>> T max(T a, T b) {
        return a.compareTo(b) > 0 ? a : b;
    }

    public static <T extends Comparable<T>> T min(T a, T b) {
        return a.compareTo(b) < 0 ? a : b;
    }

    public static void main(String[] args) {
        System.out.println("Bounded generic methods:\n");

        System.out.println("  max(5, 10): " + max(5, 10));
        System.out.println("  max('a', 'z'): " + max('a', 'z'));
        System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));

        // <T extends Type> constrains T to be Type or subclass
        // Allows calling Type's methods on T
        // Common with Comparable, Number, Serializable
        // Can combine multiple bounds with &

        System.out.println("\nSum numbers:");

        class NumberOps {
            public static <T extends Number> double sum(T[] numbers) {
                double total = 0;
                for (T num : numbers) {
                    total += num.doubleValue();
                }
                return total;
            }

            public static <T extends Number> double average(T[] numbers) {
                if (numbers.length == 0) {
                    return 0;
                }
                return sum(numbers) / numbers.length;
            }
        }

        Integer[] ints = {1, 2, 3, 4, 5};
        Double[] doubles = {1.5, 2.5, 3.5};

        System.out.println("  Sum ints: " + NumberOps.sum(ints));
        System.out.println("  Sum doubles: " + NumberOps.sum(doubles));
        System.out.println("  Average: " + NumberOps.average(ints));

        System.out.println("\nFind maximum:");

        class Finder {
            public static <T extends Comparable<T>> T findMax(T[] array) {
                if (array.length == 0) {
                    return null;
                }

                T max = array[0];
                for (T item : array) {
                    if (item.compareTo(max) > 0) {
                        max = item;
                    }
                }
                return max;
            }
        }

        System.out.println("  Max int: " + Finder.findMax(ints));

        String[] words = {"apple", "zebra", "banana", "cherry"};
        System.out.println("  Max string: " + Finder.findMax(words));

        System.out.println("\nSort array:");

        class Sorter {
            public static <T extends Comparable<T>> void sort(T[] array) {
                for (int i = 0; i < array.length - 1; i++) {
                    for (int j = i + 1; j < array.length; j++) {
                        if (array[i].compareTo(array[j]) > 0) {
                            T temp = array[i];
                            array[i] = array[j];
                            array[j] = temp;
                        }
                    }
                }
            }
        }

        Integer[] nums = {5, 2, 8, 1, 9};
        System.out.println("  Before: " + Arrays.toString(nums));
        Sorter.sort(nums);
        System.out.println("  After: " + Arrays.toString(nums));

        System.out.println("\nClamp value:");

        class RangeOps {
            public static <T extends Comparable<T>> T clamp(
                    T value, T min, T max) {
                if (value.compareTo(min) < 0) {
                    return min;
                }
                if (value.compareTo(max) > 0) {
                    return max;
                }
                return value;
            }
        }

        System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));
        System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));
        System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));

        System.out.println("\nCount greater:");

        class Counter {
            public static <T extends Comparable<T>> int countGreater(
                    T[] array, T threshold) {
                int count = 0;
                for (T item : array) {
                    if (item.compareTo(threshold) > 0) {
                        count++;
                    }
                }
                return count;
            }
        }

        int countThreshold = 5;
        System.out.println("  Count > " + countThreshold + ": " +
                         Counter.countGreater(ints, countThreshold));
        System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));
    }
}
import java.util.*;

public class Bounds {
    public static <T extends Comparable<T>> T max(T a, T b) {
        return a.compareTo(b) > 0 ? a : b;
    }

    public static <T extends Comparable<T>> T min(T a, T b) {
        return a.compareTo(b) < 0 ? a : b;
    }

    public static void main(String[] args) {
        System.out.println("Bounded generic methods:\n");

        System.out.println("  max(5, 10): " + max(5, 10));
        System.out.println("  max('a', 'z'): " + max('a', 'z'));
        System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));

        // <T extends Type> constrains T to be Type or subclass
        // Allows calling Type's methods on T
        // Common with Comparable, Number, Serializable
        // Can combine multiple bounds with &

        System.out.println("\nSum numbers:");

        class NumberOps {
            public static <T extends Number> double sum(T[] numbers) {
                double total = 0;
                for (T num : numbers) {
                    total += num.doubleValue();
                }
                return total;
            }

            public static <T extends Number> double average(T[] numbers) {
                if (numbers.length == 0) {
                    return 0;
                }
                return sum(numbers) / numbers.length;
            }
        }

        Integer[] ints = {1, 2, 3, 4, 5};
        Double[] doubles = {1.5, 2.5, 3.5};

        System.out.println("  Sum ints: " + NumberOps.sum(ints));
        System.out.println("  Sum doubles: " + NumberOps.sum(doubles));
        System.out.println("  Average: " + NumberOps.average(ints));

        System.out.println("\nFind maximum:");

        class Finder {
            public static <T extends Comparable<T>> T findMax(T[] array) {
                if (array.length == 0) {
                    return null;
                }

                T max = array[0];
                for (T item : array) {
                    if (item.compareTo(max) > 0) {
                        max = item;
                    }
                }
                return max;
            }
        }

        System.out.println("  Max int: " + Finder.findMax(ints));

        String[] words = {"apple", "zebra", "banana", "cherry"};
        System.out.println("  Max string: " + Finder.findMax(words));

        System.out.println("\nSort array:");

        class Sorter {
            public static <T extends Comparable<T>> void sort(T[] array) {
                for (int i = 0; i < array.length - 1; i++) {
                    for (int j = i + 1; j < array.length; j++) {
                        if (array[i].compareTo(array[j]) > 0) {
                            T temp = array[i];
                            array[i] = array[j];
                            array[j] = temp;
                        }
                    }
                }
            }
        }

        Integer[] nums = {5, 2, 8, 1, 9};
        System.out.println("  Before: " + Arrays.toString(nums));
        Sorter.sort(nums);
        System.out.println("  After: " + Arrays.toString(nums));

        System.out.println("\nClamp value:");

        class RangeOps {
            public static <T extends Comparable<T>> T clamp(
                    T value, T min, T max) {
                if (value.compareTo(min) < 0) {
                    return min;
                }
                if (value.compareTo(max) > 0) {
                    return max;
                }
                return value;
            }
        }

        System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));
        System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));
        System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));

        System.out.println("\nCount greater:");

        class Counter {
            public static <T extends Comparable<T>> int countGreater(
                    T[] array, T threshold) {
                int count = 0;
                for (T item : array) {
                    if (item.compareTo(threshold) > 0) {
                        count++;
                    }
                }
                return count;
            }
        }

        int countThreshold = 8;
        System.out.println("  Count > " + countThreshold + ": " +
                         Counter.countGreater(ints, countThreshold));
        System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));
    }
}
  1. public static void main(String[] args)

    12public static void main(String[] args) {13    System.out.println("Bounded generic methods:\n");14    15    System.out.println("  max(5, 10): " + max(5, 10));16    System.out.println("  max('a', 'z'): " + max('a', 'z'));
    outputBounded generic methods:
    Bounded generic methods:
  2. public static <T extends Comparable<T>> T max(T a, T b)

    pass 1 of 4
    3public class Bounds {4    public static <T extends Comparable<T>> T max(T a5, T b10) {5        return a.compareTo(b10) > 0 ? a5 : b;6    }
    All 4 passes — pass 1 is the card above
    passab
    1510
    2510
    3az
    4az
  3. System.out.println(" max(5, 10): " + max(5, 10));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));
    output  max(5, 10): 10
  4. System.out.println(" max(5, 10): " + max(5, 10));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  max(5, 10): 10
  5. System.out.println(" max('a', 'z'): " + max('a', 'z'));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  max('a', 'z'): z
  6. System.out.println(" max('a', 'z'): " + max('a', 'z'));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  max('a', 'z'): z
  7. public static <T extends Comparable<T>> T min(T a, T b)

    pass 1 of 2
    8public static <T extends Comparable<T>> T min(T aapple, T bbanana) {9    return a.compareTo(bbanana) < 0 ? aapple : b;10}
  8. System.out.println(" min(\"apple\", \"banana\"): " + min("apple", "ba…

    16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  min("apple", "banana"): apple
  9. public static <T extends Comparable<T>> T min(T a, T b)

    pass 2 of 2
    8public static <T extends Comparable<T>> T min(T aapple, T bbanana) {9    return a.compareTo(bbanana) < 0 ? aapple : b;10}
  10. System.out.println(" Sum ints: " + NumberOps.sum(ints));

    16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));1819// <T extends Type> constrains T to be Type or subclass20// Allows calling Type's methods on T21// Common with Comparable, Number, Serializable22// Can combine multiple bounds with &2324System.out.println("\nSum numbers:");2526class NumberOps {27    public static <T extends Number> double sum(T[] numbers) {28        double total = 0;29        for (T num : numbers) {30            total += num.doubleValue();31        }32        return total;33    }34    35    public static <T extends Number> double average(T[] numbers) {36        if (numbers.length == 0) {37            return 0;38        }39        return sum(numbers) / numbers.length;40    }41}4243Integer[] ints = {1, 2, 3, 4, 5};44Double[] doubles = {1.5, 2.5, 3.5};4546System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));
    output  min("apple", "banana"): apple
    
    Sum numbers:
    
    Sum numbers:
  11. total ← 0.0

    pass 1 of 6
    26class NumberOps {27    public static <T extends Number> double sum(T[] numbers) {28        double total→ 0.0 = 0;29        for (T num : numbers) {
    All 6 passes — pass 1 is the card above
    passtotal
    10.0
    20.0
    30.0
    40.0
    50.0
    60.0
  12. total ← 1.0

    pass 1 of 26
    28double total = 0;29for (T num1 : numbers) {30    total→ 1.0 += num.doubleValue();31}
    26 passes — pass 1 is the card above
    passnumtotal
    110.0 1.0
    221.0 3.0
    333.0 6.0
    446.0 10.0
    5510.0 15.0
    610.0 1.0
    721.0 3.0
    833.0 6.0
    946.0 10.0
    ⋯ 15 more passes ⋯
    2546.0 10.0
    26510.0 15.0
  13. return total;

    31    }32    return total15.0;33}
  14. System.out.println(" Sum ints: " + NumberOps.sum(ints));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));
    output  Sum ints: 15.0
  15. return total;

    31    }32    return total15.0;33}
  16. System.out.println(" Sum ints: " + NumberOps.sum(ints));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Sum ints: 15.0
  17. return total;

    31    }32    return total7.5;33}
  18. System.out.println(" Sum doubles: " + NumberOps.sum(doubles));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Sum doubles: 7.5
  19. return total;

    31    }32    return total7.5;33}
  20. System.out.println(" Sum doubles: " + NumberOps.sum(doubles));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Sum doubles: 7.5
  21. public static <T extends Number> double average(T[] numbers)

    pass 1 of 2
    35public static <T extends Number> double average(T[] numbers) {36    if (numbers.length == 0) {37        return 0;38    }39    return sum(numbers) / numbers.length5;40}
  22. return total;

    31    }32    return total15.0;33}
  23. System.out.println(" Average: " + NumberOps.average(ints));

    47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Average: 3.0
  24. public static <T extends Number> double average(T[] numbers)

    pass 2 of 2
    35public static <T extends Number> double average(T[] numbers) {36    if (numbers.length == 0) {37        return 0;38    }39    return sum(numbers) / numbers.length5;40}
  25. return total;

    31    }32    return total15.0;33}
  26. System.out.println(" Average: " + NumberOps.average(ints));

    47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));4950System.out.println("\nFind maximum:");
    output  Average: 3.0
    
    Find maximum:
    
    Find maximum:
  27. max ← 1

    pass 1 of 3
    52class Finder {53    public static <T extends Comparable<T>> T findMax(T[] array) {54        if (array.length == 0) {55            return null;56        }57        58        T max→ 1 = array[0]1;59        for (T item : array) {
    All 3 passes — pass 1 is the card above
    passarray[0]max
    111
    2appleapple
    3appleapple
  28. for (T item : array)

    pass 1 of 13
    58T max = array[0];59for (T item1 : array) {60    if (item.compareTo(max) > 0) {
    13 passes — pass 1 is the card above
    passitem
    11
    22
    33
    44
    55
    6apple
    7zebra
    8banana
    9cherry
    ⋯ 2 more passes ⋯
    12banana
    13cherry
  29. max ← 2

    pass 1 of 6
    59for (T item : array) {60    if (item.compareTo(max1) > 0) {61        max→ 2 = item2;62    }
    All 6 passes — pass 1 is the card above
    passitemmax
    121 2
    232 3
    343 4
    454 5
    5zebraapple zebra
    6zebraapple zebra
  30. return max;

    63    }64    return max5;65}
  31. System.out.println(" Max string: " + Finder.findMax(words));

    70String[] words = {"apple", "zebra", "banana", "cherry"};71System.out.println("  Max string: " + Finder.findMax(words));
  32. return max;

    63    }64    return maxzebra;65}
  33. System.out.println(" Max string: " + Finder.findMax(words));

    70String[] words = {"apple", "zebra", "banana", "cherry"};71System.out.println("  Max string: " + Finder.findMax(words));
    output  Max string: zebra
  34. return max;

    63    }64    return maxzebra;65}
  35. System.out.println(" Max string: " + Finder.findMax(words));

    70String[] words = {"apple", "zebra", "banana", "cherry"};71System.out.println("  Max string: " + Finder.findMax(words));7273System.out.println("\nSort array:");7475class Sorter {76    public static <T extends Comparable<T>> void sort(T[] array) {77        for (int i = 0; i < array.length - 1; i++) {78            for (int j = i + 1; j < array.length; j++) {79                if (array[i].compareTo(array[j]) > 0) {80                    T temp = array[i];81                    array[i] = array[j];82                    array[j] = temp;83                }84            }85        }86    }87}8889Integer[] nums = {5, 2, 8, 1, 9};90System.out.println("  Before: " + Arrays.toString(nums));91Sorter.sort(nums);
    output  Max string: zebra
    
    Sort array:
    
    Sort array:
      Before: [5, 2, 8, 1, 9]
      Before: [5, 2, 8, 1, 9]
  36. public static <T extends Comparable<T>> void sort(T[] array)

    75class Sorter {76    public static <T extends Comparable<T>> void sort(T[] array) {77        for (int i = 0; i < array.length - 1; i++) {
  37. for (int i = 0; i < array.length - 1; i++)

    pass 1 of 4
    76public static <T extends Comparable<T>> void sort(T[] array) {77    for (int i0 = 0; i < array.length5 - 1; i++) {78        for (int j = i + 1; j < array.length; j++) {
    All 4 passes — pass 1 is the card above
    passi
    10
    21
    32
    43
  38. for (int j = i + 1; j < array.length; j++)

    pass 1 of 10
    77for (int i = 0; i < array.length - 1; i++) {78    for (int j1 = i0 + 1; j < array.length5; j++) {79        if (array[i].compareTo(array[j]) > 0) {
    All 10 passes — pass 1 is the card above
    passji
    110
    220
    330
    440
    521
    631
    741
    832
    942
    1043
  39. temp ← 5, array[i] ← 2, array[j] ← 5

    pass 1 of 4
    78for (int j = i + 1; j < array.length; j++) {79    if (array[i]5.compareTo(array[j]2) > 0) {80        T temp→ 5 = array[i]5;81        array[i]→ 2 = array[j]2;82        array[j]→ 5 = temp5;83    }
    All 4 passes — pass 1 is the card above
    passijtemparray[i]array[j]
    10155 22 5
    20322 11 2
    31355 22 5
    42388 55 8
  40. System.out.println(" After: " + Arrays.toString(nums));

    91Sorter.sort(nums);92System.out.println("  After: " + Arrays.toString(nums));9394System.out.println("\nClamp value:");
    output  After: [1, 2, 5, 8, 9]
      After: [1, 2, 5, 8, 9]
    
    Clamp value:
    
    Clamp value:
  41. public static <T extends Comparable<T>> T clamp( T…

    pass 1 of 5
    96class RangeOps {97    public static <T extends Comparable<T>> T clamp(98            T value5, T min0, T max10) {99        if (value.compareTo(min) < 0) {100            return min;101        }102        if (value.compareTo(max) > 0) {103            return max;104        }105        return value5;106    }
    All 5 passes — pass 1 is the card above
    passvalue
    15
    215
    315
    4-5
    5-5
  42. System.out.println(" clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10))…

    109System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
  43. if (value.compareTo(max) > 0)

    pass 1 of 2
    101}102if (value.compareTo(max10) > 0) {103    return max10;104}
  44. System.out.println(" clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10))…

    109System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
    output  clamp(15, 0, 10): 10
  45. if (value.compareTo(max) > 0)

    pass 2 of 2
    101}102if (value.compareTo(max10) > 0) {103    return max10;104}
  46. System.out.println(" clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10))…

    109System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
    output  clamp(15, 0, 10): 10
  47. if (value.compareTo(min) < 0)

    pass 1 of 2
    98    T value, T min, T max) {99if (value.compareTo(min0) < 0) {100    return min0;101}
  48. System.out.println(" clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10))…

    110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
    output  clamp(-5, 0, 10): 0
  49. if (value.compareTo(min) < 0)

    pass 2 of 2
    98    T value, T min, T max) {99if (value.compareTo(min0) < 0) {100    return min0;101}
  50. System.out.println(" Count > " + countThreshold + ": " +

    110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));112113System.out.println("\nCount greater:");114115class Counter {116    public static <T extends Comparable<T>> int countGreater(117            T[] array, T threshold) {118        int count = 0;119        for (T item : array) {120            if (item.compareTo(threshold) > 0) {121                count++;122            }123        }124        return count;125    }126}127128int countThreshold = 3; //@countThreshold=3, 5, 8129System.out.println("  Count > " + countThreshold3 + ": " +130                 Counter.countGreater(ints, countThreshold3));131System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));
    output  clamp(-5, 0, 10): 0
    
    Count greater:
    
    Count greater:
  51. count ← 0

    pass 1 of 2
    115class Counter {116    public static <T extends Comparable<T>> int countGreater(117            T[] array, T threshold3) {118        int count→ 0 = 0;119        for (T item : array) {
  52. for (T item : array)

    pass 1 of 9
    118int count = 0;119for (T item1 : array) {120    if (item.compareTo(threshold) > 0) {
    All 9 passes — pass 1 is the card above
    passitem
    11
    22
    33
    44
    55
    6apple
    7zebra
    8banana
    9cherry
  53. count ← 1

    pass 1 of 4
    119for (T item : array) {120    if (item.compareTo(threshold3) > 0) {121        count→ 1++;122    }
    All 4 passes — pass 1 is the card above
    passthresholdcount
    130 1
    231 2
    3c0 1
    4c1 2
  54. return count;

    123    }124    return count2;125}
  55. System.out.println(" Count > " + countThreshold + ": " +

    128    int countThreshold = 3; //@countThreshold=3, 5, 8129    System.out.println("  Count > " + countThreshold3 + ": " +130                     Counter.countGreater(ints, countThreshold3));131    System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));132}
    output  Count > 3: 2
  56. count ← 0

    pass 2 of 2
    115class Counter {116    public static <T extends Comparable<T>> int countGreater(117            T[] array, T thresholdc) {118        int count→ 0 = 0;119        for (T item : array) {
  57. return count;

    123    }124    return count2;125}
  58. System.out.println(" Count > 'c': " + Counter.countGreater(words, "c"…

    130                     Counter.countGreater(ints, countThreshold));131    System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));132}
    output  Count > 'c': 2
  1. public static void main(String[] args)

    12public static void main(String[] args) {13    System.out.println("Bounded generic methods:\n");14    15    System.out.println("  max(5, 10): " + max(5, 10));16    System.out.println("  max('a', 'z'): " + max('a', 'z'));
    outputBounded generic methods:
    Bounded generic methods:
  2. public static <T extends Comparable<T>> T max(T a, T b)

    pass 1 of 4
    3public class Bounds {4    public static <T extends Comparable<T>> T max(T a5, T b10) {5        return a.compareTo(b10) > 0 ? a5 : b;6    }
    All 4 passes — pass 1 is the card above
    passab
    1510
    2510
    3az
    4az
  3. System.out.println(" max(5, 10): " + max(5, 10));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));
    output  max(5, 10): 10
  4. System.out.println(" max(5, 10): " + max(5, 10));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  max(5, 10): 10
  5. System.out.println(" max('a', 'z'): " + max('a', 'z'));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  max('a', 'z'): z
  6. System.out.println(" max('a', 'z'): " + max('a', 'z'));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  max('a', 'z'): z
  7. public static <T extends Comparable<T>> T min(T a, T b)

    pass 1 of 2
    8public static <T extends Comparable<T>> T min(T aapple, T bbanana) {9    return a.compareTo(bbanana) < 0 ? aapple : b;10}
  8. System.out.println(" min(\"apple\", \"banana\"): " + min("apple", "ba…

    16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  min("apple", "banana"): apple
  9. public static <T extends Comparable<T>> T min(T a, T b)

    pass 2 of 2
    8public static <T extends Comparable<T>> T min(T aapple, T bbanana) {9    return a.compareTo(bbanana) < 0 ? aapple : b;10}
  10. System.out.println(" Sum ints: " + NumberOps.sum(ints));

    16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));1819// <T extends Type> constrains T to be Type or subclass20// Allows calling Type's methods on T21// Common with Comparable, Number, Serializable22// Can combine multiple bounds with &2324System.out.println("\nSum numbers:");2526class NumberOps {27    public static <T extends Number> double sum(T[] numbers) {28        double total = 0;29        for (T num : numbers) {30            total += num.doubleValue();31        }32        return total;33    }34    35    public static <T extends Number> double average(T[] numbers) {36        if (numbers.length == 0) {37            return 0;38        }39        return sum(numbers) / numbers.length;40    }41}4243Integer[] ints = {1, 2, 3, 4, 5};44Double[] doubles = {1.5, 2.5, 3.5};4546System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));
    output  min("apple", "banana"): apple
    
    Sum numbers:
    
    Sum numbers:
  11. total ← 0.0

    pass 1 of 6
    26class NumberOps {27    public static <T extends Number> double sum(T[] numbers) {28        double total→ 0.0 = 0;29        for (T num : numbers) {
    All 6 passes — pass 1 is the card above
    passtotal
    10.0
    20.0
    30.0
    40.0
    50.0
    60.0
  12. total ← 1.0

    pass 1 of 26
    28double total = 0;29for (T num1 : numbers) {30    total→ 1.0 += num.doubleValue();31}
    26 passes — pass 1 is the card above
    passnumtotal
    110.0 1.0
    221.0 3.0
    333.0 6.0
    446.0 10.0
    5510.0 15.0
    610.0 1.0
    721.0 3.0
    833.0 6.0
    946.0 10.0
    ⋯ 15 more passes ⋯
    2546.0 10.0
    26510.0 15.0
  13. return total;

    31    }32    return total15.0;33}
  14. System.out.println(" Sum ints: " + NumberOps.sum(ints));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));
    output  Sum ints: 15.0
  15. return total;

    31    }32    return total15.0;33}
  16. System.out.println(" Sum ints: " + NumberOps.sum(ints));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Sum ints: 15.0
  17. return total;

    31    }32    return total7.5;33}
  18. System.out.println(" Sum doubles: " + NumberOps.sum(doubles));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Sum doubles: 7.5
  19. return total;

    31    }32    return total7.5;33}
  20. System.out.println(" Sum doubles: " + NumberOps.sum(doubles));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Sum doubles: 7.5
  21. public static <T extends Number> double average(T[] numbers)

    pass 1 of 2
    35public static <T extends Number> double average(T[] numbers) {36    if (numbers.length == 0) {37        return 0;38    }39    return sum(numbers) / numbers.length5;40}
  22. return total;

    31    }32    return total15.0;33}
  23. System.out.println(" Average: " + NumberOps.average(ints));

    47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Average: 3.0
  24. public static <T extends Number> double average(T[] numbers)

    pass 2 of 2
    35public static <T extends Number> double average(T[] numbers) {36    if (numbers.length == 0) {37        return 0;38    }39    return sum(numbers) / numbers.length5;40}
  25. return total;

    31    }32    return total15.0;33}
  26. System.out.println(" Average: " + NumberOps.average(ints));

    47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));4950System.out.println("\nFind maximum:");
    output  Average: 3.0
    
    Find maximum:
    
    Find maximum:
  27. max ← 1

    pass 1 of 3
    52class Finder {53    public static <T extends Comparable<T>> T findMax(T[] array) {54        if (array.length == 0) {55            return null;56        }57        58        T max→ 1 = array[0]1;59        for (T item : array) {
    All 3 passes — pass 1 is the card above
    passarray[0]max
    111
    2appleapple
    3appleapple
  28. for (T item : array)

    pass 1 of 13
    58T max = array[0];59for (T item1 : array) {60    if (item.compareTo(max) > 0) {
    13 passes — pass 1 is the card above
    passitem
    11
    22
    33
    44
    55
    6apple
    7zebra
    8banana
    9cherry
    ⋯ 2 more passes ⋯
    12banana
    13cherry
  29. max ← 2

    pass 1 of 6
    59for (T item : array) {60    if (item.compareTo(max1) > 0) {61        max→ 2 = item2;62    }
    All 6 passes — pass 1 is the card above
    passitemmax
    121 2
    232 3
    343 4
    454 5
    5zebraapple zebra
    6zebraapple zebra
  30. return max;

    63    }64    return max5;65}
  31. System.out.println(" Max string: " + Finder.findMax(words));

    70String[] words = {"apple", "zebra", "banana", "cherry"};71System.out.println("  Max string: " + Finder.findMax(words));
  32. return max;

    63    }64    return maxzebra;65}
  33. System.out.println(" Max string: " + Finder.findMax(words));

    70String[] words = {"apple", "zebra", "banana", "cherry"};71System.out.println("  Max string: " + Finder.findMax(words));
    output  Max string: zebra
  34. return max;

    63    }64    return maxzebra;65}
  35. System.out.println(" Max string: " + Finder.findMax(words));

    70String[] words = {"apple", "zebra", "banana", "cherry"};71System.out.println("  Max string: " + Finder.findMax(words));7273System.out.println("\nSort array:");7475class Sorter {76    public static <T extends Comparable<T>> void sort(T[] array) {77        for (int i = 0; i < array.length - 1; i++) {78            for (int j = i + 1; j < array.length; j++) {79                if (array[i].compareTo(array[j]) > 0) {80                    T temp = array[i];81                    array[i] = array[j];82                    array[j] = temp;83                }84            }85        }86    }87}8889Integer[] nums = {5, 2, 8, 1, 9};90System.out.println("  Before: " + Arrays.toString(nums));91Sorter.sort(nums);
    output  Max string: zebra
    
    Sort array:
    
    Sort array:
      Before: [5, 2, 8, 1, 9]
      Before: [5, 2, 8, 1, 9]
  36. public static <T extends Comparable<T>> void sort(T[] array)

    75class Sorter {76    public static <T extends Comparable<T>> void sort(T[] array) {77        for (int i = 0; i < array.length - 1; i++) {
  37. for (int i = 0; i < array.length - 1; i++)

    pass 1 of 4
    76public static <T extends Comparable<T>> void sort(T[] array) {77    for (int i0 = 0; i < array.length5 - 1; i++) {78        for (int j = i + 1; j < array.length; j++) {
    All 4 passes — pass 1 is the card above
    passi
    10
    21
    32
    43
  38. for (int j = i + 1; j < array.length; j++)

    pass 1 of 10
    77for (int i = 0; i < array.length - 1; i++) {78    for (int j1 = i0 + 1; j < array.length5; j++) {79        if (array[i].compareTo(array[j]) > 0) {
    All 10 passes — pass 1 is the card above
    passji
    110
    220
    330
    440
    521
    631
    741
    832
    942
    1043
  39. temp ← 5, array[i] ← 2, array[j] ← 5

    pass 1 of 4
    78for (int j = i + 1; j < array.length; j++) {79    if (array[i]5.compareTo(array[j]2) > 0) {80        T temp→ 5 = array[i]5;81        array[i]→ 2 = array[j]2;82        array[j]→ 5 = temp5;83    }
    All 4 passes — pass 1 is the card above
    passijtemparray[i]array[j]
    10155 22 5
    20322 11 2
    31355 22 5
    42388 55 8
  40. System.out.println(" After: " + Arrays.toString(nums));

    91Sorter.sort(nums);92System.out.println("  After: " + Arrays.toString(nums));9394System.out.println("\nClamp value:");
    output  After: [1, 2, 5, 8, 9]
      After: [1, 2, 5, 8, 9]
    
    Clamp value:
    
    Clamp value:
  41. public static <T extends Comparable<T>> T clamp( T…

    pass 1 of 5
    96class RangeOps {97    public static <T extends Comparable<T>> T clamp(98            T value5, T min0, T max10) {99        if (value.compareTo(min) < 0) {100            return min;101        }102        if (value.compareTo(max) > 0) {103            return max;104        }105        return value5;106    }
    All 5 passes — pass 1 is the card above
    passvalue
    15
    215
    315
    4-5
    5-5
  42. System.out.println(" clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10))…

    109System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
  43. if (value.compareTo(max) > 0)

    pass 1 of 2
    101}102if (value.compareTo(max10) > 0) {103    return max10;104}
  44. System.out.println(" clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10))…

    109System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
    output  clamp(15, 0, 10): 10
  45. if (value.compareTo(max) > 0)

    pass 2 of 2
    101}102if (value.compareTo(max10) > 0) {103    return max10;104}
  46. System.out.println(" clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10))…

    109System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
    output  clamp(15, 0, 10): 10
  47. if (value.compareTo(min) < 0)

    pass 1 of 2
    98    T value, T min, T max) {99if (value.compareTo(min0) < 0) {100    return min0;101}
  48. System.out.println(" clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10))…

    110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
    output  clamp(-5, 0, 10): 0
  49. if (value.compareTo(min) < 0)

    pass 2 of 2
    98    T value, T min, T max) {99if (value.compareTo(min0) < 0) {100    return min0;101}
  50. System.out.println(" Count > " + countThreshold + ": " +

    110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));112113System.out.println("\nCount greater:");114115class Counter {116    public static <T extends Comparable<T>> int countGreater(117            T[] array, T threshold) {118        int count = 0;119        for (T item : array) {120            if (item.compareTo(threshold) > 0) {121                count++;122            }123        }124        return count;125    }126}127128int countThreshold = 5;129System.out.println("  Count > " + countThreshold5 + ": " +130                 Counter.countGreater(ints, countThreshold5));131System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));
    output  clamp(-5, 0, 10): 0
    
    Count greater:
    
    Count greater:
  51. count ← 0

    pass 1 of 2
    115class Counter {116    public static <T extends Comparable<T>> int countGreater(117            T[] array, T threshold5) {118        int count→ 0 = 0;119        for (T item : array) {
  52. for (T item : array)

    pass 1 of 9
    118int count = 0;119for (T item1 : array) {120    if (item.compareTo(threshold) > 0) {
    All 9 passes — pass 1 is the card above
    passitemthresholdcount
    11
    22
    33
    44
    55
    6apple
    7zebrac0 1
    8banana
    9cherryc1 2
  53. return count;

    123    }124    return count0;125}
  54. System.out.println(" Count > " + countThreshold + ": " +

    128    int countThreshold = 5;129    System.out.println("  Count > " + countThreshold5 + ": " +130                     Counter.countGreater(ints, countThreshold5));131    System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));132}
    output  Count > 5: 0
  55. count ← 0

    pass 2 of 2
    115class Counter {116    public static <T extends Comparable<T>> int countGreater(117            T[] array, T thresholdc) {118        int count→ 0 = 0;119        for (T item : array) {
  56. count ← 1

    pass 1 of 2
    119for (T item : array) {120    if (item.compareTo(thresholdc) > 0) {121        count→ 1++;122    }
  57. count ← 2

    pass 2 of 2
    119for (T item : array) {120    if (item.compareTo(thresholdc) > 0) {121        count→ 2++;122    }
  58. return count;

    123    }124    return count2;125}
  59. System.out.println(" Count > 'c': " + Counter.countGreater(words, "c"…

    130                     Counter.countGreater(ints, countThreshold));131    System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));132}
    output  Count > 'c': 2
  1. public static void main(String[] args)

    12public static void main(String[] args) {13    System.out.println("Bounded generic methods:\n");14    15    System.out.println("  max(5, 10): " + max(5, 10));16    System.out.println("  max('a', 'z'): " + max('a', 'z'));
    outputBounded generic methods:
    Bounded generic methods:
  2. public static <T extends Comparable<T>> T max(T a, T b)

    pass 1 of 4
    3public class Bounds {4    public static <T extends Comparable<T>> T max(T a5, T b10) {5        return a.compareTo(b10) > 0 ? a5 : b;6    }
    All 4 passes — pass 1 is the card above
    passab
    1510
    2510
    3az
    4az
  3. System.out.println(" max(5, 10): " + max(5, 10));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));
    output  max(5, 10): 10
  4. System.out.println(" max(5, 10): " + max(5, 10));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  max(5, 10): 10
  5. System.out.println(" max('a', 'z'): " + max('a', 'z'));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  max('a', 'z'): z
  6. System.out.println(" max('a', 'z'): " + max('a', 'z'));

    15System.out.println("  max(5, 10): " + max(5, 10));16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  max('a', 'z'): z
  7. public static <T extends Comparable<T>> T min(T a, T b)

    pass 1 of 2
    8public static <T extends Comparable<T>> T min(T aapple, T bbanana) {9    return a.compareTo(bbanana) < 0 ? aapple : b;10}
  8. System.out.println(" min(\"apple\", \"banana\"): " + min("apple", "ba…

    16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));
    output  min("apple", "banana"): apple
  9. public static <T extends Comparable<T>> T min(T a, T b)

    pass 2 of 2
    8public static <T extends Comparable<T>> T min(T aapple, T bbanana) {9    return a.compareTo(bbanana) < 0 ? aapple : b;10}
  10. System.out.println(" Sum ints: " + NumberOps.sum(ints));

    16System.out.println("  max('a', 'z'): " + max('a', 'z'));17System.out.println("  min(\"apple\", \"banana\"): " + min("apple", "banana"));1819// <T extends Type> constrains T to be Type or subclass20// Allows calling Type's methods on T21// Common with Comparable, Number, Serializable22// Can combine multiple bounds with &2324System.out.println("\nSum numbers:");2526class NumberOps {27    public static <T extends Number> double sum(T[] numbers) {28        double total = 0;29        for (T num : numbers) {30            total += num.doubleValue();31        }32        return total;33    }34    35    public static <T extends Number> double average(T[] numbers) {36        if (numbers.length == 0) {37            return 0;38        }39        return sum(numbers) / numbers.length;40    }41}4243Integer[] ints = {1, 2, 3, 4, 5};44Double[] doubles = {1.5, 2.5, 3.5};4546System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));
    output  min("apple", "banana"): apple
    
    Sum numbers:
    
    Sum numbers:
  11. total ← 0.0

    pass 1 of 6
    26class NumberOps {27    public static <T extends Number> double sum(T[] numbers) {28        double total→ 0.0 = 0;29        for (T num : numbers) {
    All 6 passes — pass 1 is the card above
    passtotal
    10.0
    20.0
    30.0
    40.0
    50.0
    60.0
  12. total ← 1.0

    pass 1 of 26
    28double total = 0;29for (T num1 : numbers) {30    total→ 1.0 += num.doubleValue();31}
    26 passes — pass 1 is the card above
    passnumtotal
    110.0 1.0
    221.0 3.0
    333.0 6.0
    446.0 10.0
    5510.0 15.0
    610.0 1.0
    721.0 3.0
    833.0 6.0
    946.0 10.0
    ⋯ 15 more passes ⋯
    2546.0 10.0
    26510.0 15.0
  13. return total;

    31    }32    return total15.0;33}
  14. System.out.println(" Sum ints: " + NumberOps.sum(ints));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));
    output  Sum ints: 15.0
  15. return total;

    31    }32    return total15.0;33}
  16. System.out.println(" Sum ints: " + NumberOps.sum(ints));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Sum ints: 15.0
  17. return total;

    31    }32    return total7.5;33}
  18. System.out.println(" Sum doubles: " + NumberOps.sum(doubles));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Sum doubles: 7.5
  19. return total;

    31    }32    return total7.5;33}
  20. System.out.println(" Sum doubles: " + NumberOps.sum(doubles));

    46System.out.println("  Sum ints: " + NumberOps.sum(ints));47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Sum doubles: 7.5
  21. public static <T extends Number> double average(T[] numbers)

    pass 1 of 2
    35public static <T extends Number> double average(T[] numbers) {36    if (numbers.length == 0) {37        return 0;38    }39    return sum(numbers) / numbers.length5;40}
  22. return total;

    31    }32    return total15.0;33}
  23. System.out.println(" Average: " + NumberOps.average(ints));

    47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));
    output  Average: 3.0
  24. public static <T extends Number> double average(T[] numbers)

    pass 2 of 2
    35public static <T extends Number> double average(T[] numbers) {36    if (numbers.length == 0) {37        return 0;38    }39    return sum(numbers) / numbers.length5;40}
  25. return total;

    31    }32    return total15.0;33}
  26. System.out.println(" Average: " + NumberOps.average(ints));

    47System.out.println("  Sum doubles: " + NumberOps.sum(doubles));48System.out.println("  Average: " + NumberOps.average(ints));4950System.out.println("\nFind maximum:");
    output  Average: 3.0
    
    Find maximum:
    
    Find maximum:
  27. max ← 1

    pass 1 of 3
    52class Finder {53    public static <T extends Comparable<T>> T findMax(T[] array) {54        if (array.length == 0) {55            return null;56        }57        58        T max→ 1 = array[0]1;59        for (T item : array) {
    All 3 passes — pass 1 is the card above
    passarray[0]max
    111
    2appleapple
    3appleapple
  28. for (T item : array)

    pass 1 of 13
    58T max = array[0];59for (T item1 : array) {60    if (item.compareTo(max) > 0) {
    13 passes — pass 1 is the card above
    passitem
    11
    22
    33
    44
    55
    6apple
    7zebra
    8banana
    9cherry
    ⋯ 2 more passes ⋯
    12banana
    13cherry
  29. max ← 2

    pass 1 of 6
    59for (T item : array) {60    if (item.compareTo(max1) > 0) {61        max→ 2 = item2;62    }
    All 6 passes — pass 1 is the card above
    passitemmax
    121 2
    232 3
    343 4
    454 5
    5zebraapple zebra
    6zebraapple zebra
  30. return max;

    63    }64    return max5;65}
  31. System.out.println(" Max string: " + Finder.findMax(words));

    70String[] words = {"apple", "zebra", "banana", "cherry"};71System.out.println("  Max string: " + Finder.findMax(words));
  32. return max;

    63    }64    return maxzebra;65}
  33. System.out.println(" Max string: " + Finder.findMax(words));

    70String[] words = {"apple", "zebra", "banana", "cherry"};71System.out.println("  Max string: " + Finder.findMax(words));
    output  Max string: zebra
  34. return max;

    63    }64    return maxzebra;65}
  35. System.out.println(" Max string: " + Finder.findMax(words));

    70String[] words = {"apple", "zebra", "banana", "cherry"};71System.out.println("  Max string: " + Finder.findMax(words));7273System.out.println("\nSort array:");7475class Sorter {76    public static <T extends Comparable<T>> void sort(T[] array) {77        for (int i = 0; i < array.length - 1; i++) {78            for (int j = i + 1; j < array.length; j++) {79                if (array[i].compareTo(array[j]) > 0) {80                    T temp = array[i];81                    array[i] = array[j];82                    array[j] = temp;83                }84            }85        }86    }87}8889Integer[] nums = {5, 2, 8, 1, 9};90System.out.println("  Before: " + Arrays.toString(nums));91Sorter.sort(nums);
    output  Max string: zebra
    
    Sort array:
    
    Sort array:
      Before: [5, 2, 8, 1, 9]
      Before: [5, 2, 8, 1, 9]
  36. public static <T extends Comparable<T>> void sort(T[] array)

    75class Sorter {76    public static <T extends Comparable<T>> void sort(T[] array) {77        for (int i = 0; i < array.length - 1; i++) {
  37. for (int i = 0; i < array.length - 1; i++)

    pass 1 of 4
    76public static <T extends Comparable<T>> void sort(T[] array) {77    for (int i0 = 0; i < array.length5 - 1; i++) {78        for (int j = i + 1; j < array.length; j++) {
    All 4 passes — pass 1 is the card above
    passi
    10
    21
    32
    43
  38. for (int j = i + 1; j < array.length; j++)

    pass 1 of 10
    77for (int i = 0; i < array.length - 1; i++) {78    for (int j1 = i0 + 1; j < array.length5; j++) {79        if (array[i].compareTo(array[j]) > 0) {
    All 10 passes — pass 1 is the card above
    passji
    110
    220
    330
    440
    521
    631
    741
    832
    942
    1043
  39. temp ← 5, array[i] ← 2, array[j] ← 5

    pass 1 of 4
    78for (int j = i + 1; j < array.length; j++) {79    if (array[i]5.compareTo(array[j]2) > 0) {80        T temp→ 5 = array[i]5;81        array[i]→ 2 = array[j]2;82        array[j]→ 5 = temp5;83    }
    All 4 passes — pass 1 is the card above
    passijtemparray[i]array[j]
    10155 22 5
    20322 11 2
    31355 22 5
    42388 55 8
  40. System.out.println(" After: " + Arrays.toString(nums));

    91Sorter.sort(nums);92System.out.println("  After: " + Arrays.toString(nums));9394System.out.println("\nClamp value:");
    output  After: [1, 2, 5, 8, 9]
      After: [1, 2, 5, 8, 9]
    
    Clamp value:
    
    Clamp value:
  41. public static <T extends Comparable<T>> T clamp( T…

    pass 1 of 5
    96class RangeOps {97    public static <T extends Comparable<T>> T clamp(98            T value5, T min0, T max10) {99        if (value.compareTo(min) < 0) {100            return min;101        }102        if (value.compareTo(max) > 0) {103            return max;104        }105        return value5;106    }
    All 5 passes — pass 1 is the card above
    passvalue
    15
    215
    315
    4-5
    5-5
  42. System.out.println(" clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10))…

    109System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
  43. if (value.compareTo(max) > 0)

    pass 1 of 2
    101}102if (value.compareTo(max10) > 0) {103    return max10;104}
  44. System.out.println(" clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10))…

    109System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
    output  clamp(15, 0, 10): 10
  45. if (value.compareTo(max) > 0)

    pass 2 of 2
    101}102if (value.compareTo(max10) > 0) {103    return max10;104}
  46. System.out.println(" clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10))…

    109System.out.println("  clamp(5, 0, 10): " + RangeOps.clamp(5, 0, 10));110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
    output  clamp(15, 0, 10): 10
  47. if (value.compareTo(min) < 0)

    pass 1 of 2
    98    T value, T min, T max) {99if (value.compareTo(min0) < 0) {100    return min0;101}
  48. System.out.println(" clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10))…

    110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));
    output  clamp(-5, 0, 10): 0
  49. if (value.compareTo(min) < 0)

    pass 2 of 2
    98    T value, T min, T max) {99if (value.compareTo(min0) < 0) {100    return min0;101}
  50. System.out.println(" Count > " + countThreshold + ": " +

    110System.out.println("  clamp(15, 0, 10): " + RangeOps.clamp(15, 0, 10));111System.out.println("  clamp(-5, 0, 10): " + RangeOps.clamp(-5, 0, 10));112113System.out.println("\nCount greater:");114115class Counter {116    public static <T extends Comparable<T>> int countGreater(117            T[] array, T threshold) {118        int count = 0;119        for (T item : array) {120            if (item.compareTo(threshold) > 0) {121                count++;122            }123        }124        return count;125    }126}127128int countThreshold = 8;129System.out.println("  Count > " + countThreshold8 + ": " +130                 Counter.countGreater(ints, countThreshold8));131System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));
    output  clamp(-5, 0, 10): 0
    
    Count greater:
    
    Count greater:
  51. count ← 0

    pass 1 of 2
    115class Counter {116    public static <T extends Comparable<T>> int countGreater(117            T[] array, T threshold8) {118        int count→ 0 = 0;119        for (T item : array) {
  52. for (T item : array)

    pass 1 of 9
    118int count = 0;119for (T item1 : array) {120    if (item.compareTo(threshold) > 0) {
    All 9 passes — pass 1 is the card above
    passitemthresholdcount
    11
    22
    33
    44
    55
    6apple
    7zebrac0 1
    8banana
    9cherryc1 2
  53. return count;

    123    }124    return count0;125}
  54. System.out.println(" Count > " + countThreshold + ": " +

    128    int countThreshold = 8;129    System.out.println("  Count > " + countThreshold8 + ": " +130                     Counter.countGreater(ints, countThreshold8));131    System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));132}
    output  Count > 8: 0
  55. count ← 0

    pass 2 of 2
    115class Counter {116    public static <T extends Comparable<T>> int countGreater(117            T[] array, T thresholdc) {118        int count→ 0 = 0;119        for (T item : array) {
  56. count ← 1

    pass 1 of 2
    119for (T item : array) {120    if (item.compareTo(thresholdc) > 0) {121        count→ 1++;122    }
  57. count ← 2

    pass 2 of 2
    119for (T item : array) {120    if (item.compareTo(thresholdc) > 0) {121        count→ 2++;122    }
  58. return count;

    123    }124    return count2;125}
  59. System.out.println(" Count > 'c': " + Counter.countGreater(words, "c"…

    130                     Counter.countGreater(ints, countThreshold));131    System.out.println("  Count > 'c': " + Counter.countGreater(words, "c"));132}
    output  Count > 'c': 2

<T extends Comparable<T>> - T must be comparable to itself.

Static generic methods

Static methods can be generic even in non-generic classes.

Static.java
Replay: real traced execution (multi-file project)
import java.util.*;

public class Static {
    static class CollectionUtils {
        public static <T> List<T> newArrayList() {
            return new ArrayList<>();
        }

        public static <K, V> Map<K, V> newHashMap() {
            return new LinkedHashMap<>();
        }

        public static <T> Set<T> newHashSet() {
            return new LinkedHashSet<>();
        }
    }

    public static void main(String[] args) {
        System.out.println("Static generic methods:\n");

        List<String> list = CollectionUtils.newArrayList();
        list.add("a");
        list.add("b");

        Map<String, Integer> map = CollectionUtils.newHashMap();
        map.put("one", 1);
        map.put("two", 2);

        System.out.println("  List: " + list);
        System.out.println("  Map: " + map);

        // Static methods can be generic
        // Don't need generic class
        // Type parameters independent of class
        // Common in utility classes

        System.out.println("\nCreate from varargs:");

        class ListFactory {
            @SafeVarargs
            public static <T> List<T> of(T... items) {
                List<T> list = new ArrayList<>();
                for (T item : items) {
                    list.add(item);
                }
                return list;
            }
        }

        List<Integer> nums = ListFactory.of(1, 2, 3, 4, 5);
        List<String> words = ListFactory.of("a", "b", "c");

        System.out.println("  Numbers: " + nums);
        System.out.println("  Words: " + words);

        System.out.println("\nCopy collections:");

        class Copier {
            public static <T> void copy(
                    Collection<T> dest,
                    Collection<T> src) {
                dest.clear();
                dest.addAll(src);
            }

            public static <T> List<T> copyToList(Collection<T> src) {
                return new ArrayList<>(src);
            }
        }

        Set<String> source = new LinkedHashSet<>(Arrays.asList("x", "y", "z"));
        List<String> dest = new ArrayList<>();

        Copier.copy(dest, source);
        System.out.println("  Copied: " + dest);

        System.out.println("\nReverse:");

        class Reverser {
            public static <T> List<T> reverse(List<T> list) {
                List<T> result = new ArrayList<>();
                for (int i = list.size() - 1; i >= 0; i--) {
                    result.add(list.get(i));
                }
                return result;
            }
        }

        List<Integer> original = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> reversed = Reverser.reverse(original);

        System.out.println("  Original: " + original);
        System.out.println("  Reversed: " + reversed);

        System.out.println("\nFilter:");

        interface Predicate<T> {
            boolean test(T item);
        }

        class Filter {
            public static <T> List<T> filter(
                    Collection<T> collection,
                    Predicate<T> predicate) {
                List<T> result = new ArrayList<>();
                for (T item : collection) {
                    if (predicate.test(item)) {
                        result.add(item);
                    }
                }
                return result;
            }
        }

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        int divisor = 2;
        List<Integer> evens = Filter.filter(numbers, n -> n % divisor == 0);

        System.out.println("  Divisible by " + divisor + ": " + evens);

        System.out.println("\nTransform:");

        interface Function<T, R> {
            R apply(T item);
        }

        class Transformer {
            public static <T, R> List<R> map(
                    Collection<T> collection,
                    Function<T, R> mapper) {
                List<R> result = new ArrayList<>();
                for (T item : collection) {
                    result.add(mapper.apply(item));
                }
                return result;
            }
        }

        List<String> strings = Arrays.asList("1", "2", "3");
        List<Integer> parsed = Transformer.map(strings, Integer::parseInt);

        System.out.println("  Strings: " + strings);
        System.out.println("  Parsed: " + parsed);
    }
}
  1. public static void main(String[] args)

    18public static void main(String[] args) {19    System.out.println("Static generic methods:\n");
    outputStatic generic methods:
    Static generic methods:
  2. System.out.println(" List: " + list);

    29System.out.println("  List: " + list[a, b]);30System.out.println("  Map: " + map{one=1, two=2});3132// Static methods can be generic33// Don't need generic class34// Type parameters independent of class35// Common in utility classes3637System.out.println("\nCreate from varargs:");
    output  List: [a, b]
      List: [a, b]
      Map: {one=1, two=2}
      Map: {one=1, two=2}
    
    Create from varargs:
    
    Create from varargs:
  3. list ← []

    pass 1 of 2
    39class ListFactory {40    @SafeVarargs41    public static <T> List<T> of(T... items) {42        List<T> list→ [] = new ArrayList<>();43        for (T item : items) {
  4. for (T item : items)

    pass 1 of 8
    42List<T> list = new ArrayList<>();43for (T item1 : items) {44    list.add(item1);45}
    All 8 passes — pass 1 is the card above
    passitem
    11
    22
    33
    44
    55
    6a
    7b
    8c
  5. return list;

    45    }46    return list[1, 2, 3, 4, 5];47}
  6. list ← []

    pass 2 of 2
    39class ListFactory {40    @SafeVarargs41    public static <T> List<T> of(T... items) {42        List<T> list→ [] = new ArrayList<>();43        for (T item : items) {
  7. return list;

    45    }46    return list[a, b, c];47}
  8. System.out.println(" Numbers: " + nums);

    53System.out.println("  Numbers: " + nums[1, 2, 3, 4, 5]);54System.out.println("  Words: " + words[a, b, c]);5556System.out.println("\nCopy collections:");
    output  Numbers: [1, 2, 3, 4, 5]
      Numbers: [1, 2, 3, 4, 5]
      Words: [a, b, c]
      Words: [a, b, c]
    
    Copy collections:
    
    Copy collections:
  9. public static <T> void copy( Collection<T> dest, …

    58class Copier {59    public static <T> void copy(60            Collection<T> dest[],61            Collection<T> src[x, y, z]) {62        dest.clear();63        dest.addAll(src[x, y, z]);64    }
  10. System.out.println(" Copied: " + dest);

    74Copier.copy(dest, source);75System.out.println("  Copied: " + dest[x, y, z]);7677System.out.println("\nReverse:");7879class Reverser {80    public static <T> List<T> reverse(List<T> list) {81        List<T> result = new ArrayList<>();82        for (int i = list.size() - 1; i >= 0; i--) {83            result.add(list.get(i));84        }85        return result;86    }87}8889List<Integer> original = Arrays.asList(1, 2, 3, 4, 5);90List<Integer> reversed = Reverser.reverse(original[1, 2, 3, 4, 5]);
    output  Copied: [x, y, z]
      Copied: [x, y, z]
    
    Reverse:
    
    Reverse:
  11. result ← []

    79class Reverser {80    public static <T> List<T> reverse(List<T> list[1, 2, 3, 4, 5]) {81        List<T> result→ [] = new ArrayList<>();82        for (int i = list.size() - 1; i >= 0; i--) {
  12. for (int i = list.size() - 1; i >= 0; i--)

    pass 1 of 5
    81List<T> result = new ArrayList<>();82for (int i4 = list.size() - 1; i >= 0; i--) {83    result.add(list.get(i4));84}
    All 5 passes — pass 1 is the card above
    passi
    14
    23
    32
    41
    50
  13. return result;

    84    }85    return result[5, 4, 3, 2, 1];86}
  14. reversed ← [5, 4, 3, 2, 1], divisor ← 2

    89List<Integer> original = Arrays.asList(1, 2, 3, 4, 5);90List<Integer> reversed→ [5, 4, 3, 2, 1] = Reverser.reverse(original[1, 2, 3, 4, 5]);9192System.out.println("  Original: " + original[1, 2, 3, 4, 5]);93System.out.println("  Reversed: " + reversed[5, 4, 3, 2, 1]);9495System.out.println("\nFilter:");9697interface Predicate<T> {98    boolean test(T item);99}100101class Filter {102    public static <T> List<T> filter(103            Collection<T> collection,104            Predicate<T> predicate) {105        List<T> result = new ArrayList<>();106        for (T item : collection) {107            if (predicate.test(item)) {108                result.add(item);109            }110        }111        return result;112    }113}114115List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);116int divisor→ 2 = 2;117List<Integer> evens = Filter.filter(numbers[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], n -> n % divisor == 0);
    output  Original: [1, 2, 3, 4, 5]
      Reversed: [5, 4, 3, 2, 1]
    
    Filter:
  15. result ← []

    101class Filter {102    public static <T> List<T> filter(103            Collection<T> collection[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],104            Predicate<T> predicate⟨Static lambda A⟩) {105        List<T> result→ [] = new ArrayList<>();106        for (T item : collection) {
  16. for (T item : collection)

    pass 1 of 10
    105List<T> result = new ArrayList<>();106for (T item1 : collection[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) {107    if (predicate.test(item)) {
    All 10 passes — pass 1 is the card above
    passitem
    11
    22
    33
    44
    55
    66
    77
    88
    99
    1010
  17. if (predicate.test(item))

    pass 1 of 5
    106for (T item : collection) {107    if (predicate.test(item2)) {108        result.add(item2);109    }
    All 5 passes — pass 1 is the card above
    passitem
    12
    24
    36
    48
    510
  18. return result;

    110    }111    return result[2, 4, 6, 8, 10];112}
  19. evens ← [2, 4, 6, 8, 10]

    116int divisor = 2;117List<Integer> evens→ [2, 4, 6, 8, 10] = Filter.filter(numbers[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], n -> n % divisor == 0);118119System.out.println("  Divisible by " + divisor2 + ": " + evens[2, 4, 6, 8, 10]);120121System.out.println("\nTransform:");122123interface Function<T, R> {124    R apply(T item);125}126127class Transformer {128    public static <T, R> List<R> map(129            Collection<T> collection,130            Function<T, R> mapper) {131        List<R> result = new ArrayList<>();132        for (T item : collection) {133            result.add(mapper.apply(item));134        }135        return result;136    }137}138139List<String> strings = Arrays.asList("1", "2", "3");140List<Integer> parsed = Transformer.map(strings[1, 2, 3], Integer::parseInt);
    output  Divisible by 2: [2, 4, 6, 8, 10]
    
    Transform:
  20. result ← []

    127class Transformer {128    public static <T, R> List<R> map(129            Collection<T> collection[1, 2, 3],130            Function<T, R> mapper⟨Static lambda B⟩) {131        List<R> result→ [] = new ArrayList<>();132        for (T item : collection) {
  21. for (T item : collection)

    pass 1 of 3
    131List<R> result = new ArrayList<>();132for (T item1 : collection[1, 2, 3]) {133    result.add(mapper.apply(item1));134}
    All 3 passes — pass 1 is the card above
    passitem
    11
    22
    33
  22. return result;

    134    }135    return result[1, 2, 3];136}
  23. parsed ← [1, 2, 3]

    139    List<String> strings = Arrays.asList("1", "2", "3");140    List<Integer> parsed→ [1, 2, 3] = Transformer.map(strings[1, 2, 3], Integer::parseInt);141    142    System.out.println("  Strings: " + strings[1, 2, 3]);143    System.out.println("  Parsed: " + parsed[1, 2, 3]);144}
    output  Strings: [1, 2, 3]
      Parsed: [1, 2, 3]

public static <T> T identity(T val) - no instance needed.

Type inference

Compiler infers type from arguments.

Inference.java
Replay: real traced execution (multi-file project)
import java.util.*;

public class Inference {
    public static <T> T identity(T value) {
        return value;
    }

    public static <K, V> Map<K, V> createMap(K key, V value) {
        Map<K, V> map = new HashMap<>();
        map.put(key, value);
        return map;
    }

    public static void main(String[] args) {
        System.out.println("Type inference:\n");

        // Explicit type argument
        String s1 = Inference.<String>identity("hello");

        // Inferred type argument (preferred)
        String s2 = identity("hello");

        System.out.println("  Explicit: " + s1);
        System.out.println("  Inferred: " + s2);

        // Java can infer type parameters from arguments
        // Explicit: ClassName.<Type>method(arg)
        // Inferred: ClassName.method(arg) - preferred
        // Inference works with return type context

        System.out.println("\nInferred from arguments:");

        class Pair<K, V> {
            K key;
            V value;

            Pair(K key, V value) {
                this.key = key;
                this.value = value;
            }

            public String toString() {
                return "(" + key + ", " + value + ")";
            }
        }

        class PairFactory {
            public static <K, V> Pair<K, V> make(K key, V value) {
                return new Pair<>(key, value);
            }
        }

        // Type inferred from arguments
        Pair<String, Integer> p1 = PairFactory.make("age", 30);
        Pair<Integer, String> p2 = PairFactory.make(1, "first");

        System.out.println("  Pair 1: " + p1);
        System.out.println("  Pair 2: " + p2);

        System.out.println("\nDiamond operator:");

        // Before Java 7 - redundant
        Map<String, List<Integer>> old =
            new HashMap<String, List<Integer>>();

        // Java 7+ - inferred
        Map<String, List<Integer>> modern = new HashMap<>();

        modern.put("nums", Arrays.asList(1, 2, 3));
        System.out.println("  Map: " + modern);

        System.out.println("\nInferred return type:");

        class Builder {
            public static <T> List<T> build(T... items) {
                List<T> list = new ArrayList<>();
                for (T item : items) {
                    list.add(item);
                }
                return list;
            }
        }

        List<String> words = Builder.build("a", "b", "c");
        List<Integer> nums = Builder.build(1, 2, 3);

        System.out.println("  Words: " + words);
        System.out.println("  Numbers: " + nums);

        System.out.println("\nComplex inference:");

        class Wrapper<T> {
            T value;

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

            public String toString() {
                return "Wrapper(" + value + ")";
            }
        }

        class WrapperFactory {
            public static <T> Wrapper<T> wrap(T value) {
                return new Wrapper<>(value);
            }

            public static <T> List<Wrapper<T>> wrapAll(List<T> values) {
                List<Wrapper<T>> result = new ArrayList<>();
                for (T value : values) {
                    result.add(wrap(value));
                }
                return result;
            }
        }

        List<Integer> numbers = Arrays.asList(1, 2, 3);
        List<Wrapper<Integer>> wrapped = WrapperFactory.wrapAll(numbers);

        System.out.println("  Wrapped: " + wrapped);

        System.out.println("\nTarget type:");

        class Utils {
            public static <T> List<T> emptyList() {
                return new ArrayList<>();
            }
        }

        // Type inferred from variable declaration
        List<String> empty1 = Utils.emptyList();
        List<Integer> empty2 = Utils.emptyList();

        System.out.println("  Empty string list: " + empty1);
        System.out.println("  Empty int list: " + empty2);

        System.out.println("\nMethod chaining:");

        class FluentBuilder<T> {
            private List<T> items = new ArrayList<>();

            public static <T> FluentBuilder<T> create() {
                return new FluentBuilder<>();
            }

            public FluentBuilder<T> add(T item) {
                items.add(item);
                return this;
            }

            public List<T> build() {
                return items;
            }
        }

        List<String> result = FluentBuilder.<String>create()  // Explicit
            .add("a")
            .add("b")
            .add("c")
            .build();

        List<Integer> result2 = FluentBuilder.<Integer>create()  // Also explicit - chains need hint
            .add(1)
            .add(2)
            .add(3)
            .build();

        System.out.println("  Result 1: " + result);
        System.out.println("  Result 2: " + result2);
    }
}
  1. public static void main(String[] args)

    14public static void main(String[] args) {15    System.out.println("Type inference:\n");
    outputType inference:
    Type inference:
  2. public static <T> T identity(T value)

    pass 1 of 2
    3public class Inference {4    public static <T> T identity(T valuehello) {5        return valuehello;6    }
  3. public static <T> T identity(T value)

    pass 2 of 2
    3public class Inference {4    public static <T> T identity(T valuehello) {5        return valuehello;6    }
  4. System.out.println(" Explicit: " + s1);

    23System.out.println("  Explicit: " + s1hello);24System.out.println("  Inferred: " + s2hello);2526// Java can infer type parameters from arguments27// Explicit: ClassName.<Type>method(arg)28// Inferred: ClassName.method(arg) - preferred29// Inference works with return type context3031System.out.println("\nInferred from arguments:");
    output  Explicit: hello
      Explicit: hello
      Inferred: hello
      Inferred: hello
    
    Inferred from arguments:
    
    Inferred from arguments:
  5. public static <K, V> Pair<K, V> make(K key, V value)

    pass 1 of 2
    47class PairFactory {48    public static <K, V> Pair<K, V> make(K keyage, V value30) {49        return new Pair<>(key, value);50    }
  6. this.key ← age, this.value ← 30

    pass 1 of 2
    37Pair(K keyage, V value30) {38    this.key→ age = keyage;39    this.value→ 30 = value30;40}
  7. public static <K, V> Pair<K, V> make(K key, V value)

    pass 2 of 2
    47class PairFactory {48    public static <K, V> Pair<K, V> make(K key1, V valuefirst) {49        return new Pair<>(key, value);50    }
  8. this.key ← 1, this.value ← first

    pass 2 of 2
    37Pair(K key1, V valuefirst) {38    this.key→ 1 = key1;39    this.value→ first = valuefirst;40}
  9. System.out.println(" Pair 1: " + p1);

    57System.out.println("  Pair 1: " + p1(age, 30));58System.out.println("  Pair 2: " + p2(1, first));5960System.out.println("\nDiamond operator:");6162// Before Java 7 - redundant63Map<String, List<Integer>> old = 64    new HashMap<String, List<Integer>>();6566// Java 7+ - inferred67Map<String, List<Integer>> modern = new HashMap<>();6869modern.put("nums", Arrays.asList(1, 2, 3));70System.out.println("  Map: " + modern{nums=[1, 2, 3]});7172System.out.println("\nInferred return type:");
    output  Pair 1: (age, 30)
      Pair 1: (age, 30)
      Pair 2: (1, first)
      Pair 2: (1, first)
    
    Diamond operator:
    
    Diamond operator:
      Map: {nums=[1, 2, 3]}
      Map: {nums=[1, 2, 3]}
    
    Inferred return type:
    
    Inferred return type:
  10. list ← []

    pass 1 of 2
    74class Builder {75    public static <T> List<T> build(T... items) {76        List<T> list→ [] = new ArrayList<>();77        for (T item : items) {
  11. for (T item : items)

    pass 1 of 6
    76List<T> list = new ArrayList<>();77for (T itema : items) {78    list.add(itema);79}
    All 6 passes — pass 1 is the card above
    passitem
    1a
    2b
    3c
    41
    52
    63
  12. return list;

    79    }80    return list[a, b, c];81}
  13. list ← []

    pass 2 of 2
    74class Builder {75    public static <T> List<T> build(T... items) {76        List<T> list→ [] = new ArrayList<>();77        for (T item : items) {
  14. return list;

    79    }80    return list[1, 2, 3];81}
  15. System.out.println(" Words: " + words);

    87System.out.println("  Words: " + words[a, b, c]);88System.out.println("  Numbers: " + nums[1, 2, 3]);8990System.out.println("\nComplex inference:");
    output  Words: [a, b, c]
      Words: [a, b, c]
      Numbers: [1, 2, 3]
      Numbers: [1, 2, 3]
    
    Complex inference:
    
    Complex inference:
  16. result ← []

    109public static <T> List<Wrapper<T>> wrapAll(List<T> values[1, 2, 3]) {110    List<Wrapper<T>> result→ [] = new ArrayList<>();111    for (T value : values) {
  17. for (T value : values)

    pass 1 of 3
    110List<Wrapper<T>> result = new ArrayList<>();111for (T value1 : values[1, 2, 3]) {112    result.add(wrap(value1));113}
    All 3 passes — pass 1 is the card above
    passvalue
    11
    22
    33
  18. public static <T> Wrapper<T> wrap(T value)

    pass 1 of 3
    104class WrapperFactory {105    public static <T> Wrapper<T> wrap(T value1) {106        return new Wrapper<>(value);107    }
    All 3 passes — pass 1 is the card above
    passvalue
    11
    22
    33
  19. this.value ← 1

    pass 1 of 3
    95Wrapper(T value1) {96    this.value→ 1 = value1;97}
    All 3 passes — pass 1 is the card above
    passvaluethis.value
    111
    222
    333
  20. result.add(wrap(value));

    111for (T value : values) {112    result.add(wrap(value1));113}
  21. result.add(wrap(value));

    111for (T value : values) {112    result.add(wrap(value2));113}
  22. result.add(wrap(value));

    111for (T value : values) {112    result.add(wrap(value3));113}
  23. return result;

    113    }114    return result[Wrapper(1), Wrapper(2), Wrapper(3)];115}
  24. System.out.println(" Wrapped: " + wrapped);

    121System.out.println("  Wrapped: " + wrapped[Wrapper(1), Wrapper(2), Wrapper(3)]);122123System.out.println("\nTarget type:");
    output  Wrapped: [Wrapper(1), Wrapper(2), Wrapper(3)]
      Wrapped: [Wrapper(1), Wrapper(2), Wrapper(3)]
    
    Target type:
    
    Target type:
  25. System.out.println(" Empty string list: " + empty1);

    135System.out.println("  Empty string list: " + empty1[]);136System.out.println("  Empty int list: " + empty2[]);137138System.out.println("\nMethod chaining:");
    output  Empty string list: []
      Empty string list: []
      Empty int list: []
      Empty int list: []
    
    Method chaining:
    
    Method chaining:
  26. public FluentBuilder<T> add(T item)

    pass 1 of 6
    147public FluentBuilder<T> add(T itema) {148    items.add(itema);149    return this;150}
    All 6 passes — pass 1 is the card above
    passitemitems
    1a
    2b
    3c[a, b, c]
    41
    52
    63[1, 2, 3]
  27. public List<T> build()

    pass 1 of 2
    152public List<T> build() {153    return items[a, b, c];154}
  28. List<Integer> result2 = FluentBuilder.<Integer>create() // Also expli…

    163List<Integer> result2 = FluentBuilder.<Integer>create()  // Also explicit - chains need hint164    .add(1)165    .add(2)166    .add(3)167    .build();
  29. public List<T> build()

    pass 2 of 2
    152public List<T> build() {153    return items[1, 2, 3];154}
  30. result2 ← [1, 2, 3]

    163    List<Integer> result2→ [1, 2, 3] = FluentBuilder.<Integer>create()  // Also explicit - chains need hint164        .add(1)165        .add(2)166        .add(3)167        .build();168    169    System.out.println("  Result 1: " + result[a, b, c]);170    System.out.println("  Result 2: " + result2[1, 2, 3]);171}
    output  Result 1: [a, b, c]
      Result 2: [1, 2, 3]

Box.create("text") - compiler knows T is String. No explicit <String>.

type inference Compiler deduces type arguments from context. Explicit syntax rarely needed.

Generic constructors

Constructors can have their own type parameters.

rawBoxValue
Constructors.java
Replay: real traced execution (multi-file project)
import java.util.*;

public class Constructors {
    static class Box<T> {
        private T content;

        // Generic constructor - U independent of T
        <U> Box(U initialValue, Converter<U, T> converter) {
            this.content = converter.convert(initialValue);
        }

        public T get() {
            return content;
        }
    }

    interface Converter<F, T> {
        T convert(F from);
    }

    public static void main(String[] args) {
        System.out.println("Generic constructors:\n");

        // Create Box<Integer> from String
        String rawBoxValue = "42";
        Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);
        System.out.println("  Box content: " + box.get());

        // Constructors can have their own type parameters
        // Type parameters independent of class type parameters
        // Useful for type conversion during construction
        // Generic constructors enable flexible initialization

        System.out.println("\nCollection initialization:");

        class Container<T> {
            private List<T> items;

            // Non-generic constructor
            Container() {
                this.items = new ArrayList<>();
            }

            // Generic constructor
            <U> Container(Collection<U> source, Converter<U, T> converter) {
                this.items = new ArrayList<>();
                for (U item : source) {
                    items.add(converter.convert(item));
                }
            }

            public List<T> getItems() {
                return items;
            }
        }

        List<String> strings = Arrays.asList("1", "2", "3", "4", "5");
        Container<Integer> numbers = new Container<>(strings, Integer::parseInt);

        System.out.println("  Numbers: " + numbers.getItems());

        System.out.println("\nBuilder pattern:");

        class Person {
            private String name;
            private int age;

            private Person(String name, int age) {
                this.name = name;
                this.age = age;
            }

            public String toString() {
                return name + " (" + age + ")";
            }
        }

        interface Factory<T> {
            T create(Map<String, Object> props);
        }

        class Builder<T> {
            private Map<String, Object> properties = new LinkedHashMap<>();

            <U> Builder<T> set(String key, U value) {
                properties.put(key, value);
                return this;
            }

            T build(Factory<T> factory) {
                return factory.create(properties);
            }
        }

        Person person = new Builder<Person>()
            .set("name", "Alice")
            .set("age", 30)
            .build(props -> new Person(
                (String) props.get("name"),
                (Integer) props.get("age")
            ));

        System.out.println("  Person: " + person);

        System.out.println("\nCached initialization:");

        interface KeyConverter<K> {
            String convert(K key);
        }

        class Cache<T> {
            private Map<String, T> cache = new LinkedHashMap<>();

            <K> Cache(Map<K, T> initial, KeyConverter<K> converter) {
                for (Map.Entry<K, T> entry : initial.entrySet()) {
                    String key = converter.convert(entry.getKey());
                    cache.put(key, entry.getValue());
                }
            }

            public T get(String key) {
                return cache.get(key);
            }

            public Set<String> keys() {
                return cache.keySet();
            }
        }

        Map<Integer, String> data = new LinkedHashMap<>();
        data.put(1, "one");
        data.put(2, "two");
        data.put(3, "three");

        Cache<String> cache = new Cache<>(data, Object::toString);

        System.out.println("  Keys: " + cache.keys());
        System.out.println("  Value for '1': " + cache.get("1"));

        System.out.println("\nMulti-source constructor:");

        class Aggregator<T> {
            private List<T> all = new ArrayList<>();

            @SafeVarargs
            <U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {
                for (Collection<U> source : sources) {
                    for (U item : source) {
                        all.add(converter.convert(item));
                    }
                }
            }

            public List<T> getAll() {
                return all;
            }
        }

        List<String> source1 = Arrays.asList("1", "2", "3");
        List<String> source2 = Arrays.asList("4", "5", "6");

        Aggregator<Integer> agg = new Aggregator<>(
            Integer::parseInt,
            source1,
            source2
        );

        System.out.println("  Aggregated: " + agg.getAll());

        System.out.println("\nWrapper constructor:");

        interface Parser<F, T> {
            T parse(F from);
        }

        class Wrapper<T> {
            private T value;

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

            <U> Wrapper(U rawValue, Parser<U, T> parser) {
                this.value = parser.parse(rawValue);
            }

            public T getValue() {
                return value;
            }
        }

        Wrapper<Integer> w1 = new Wrapper<>(42);
        Wrapper<Integer> w2 = new Wrapper<>("123", Integer::parseInt);

        System.out.println("  Wrapper 1: " + w1.getValue());
        System.out.println("  Wrapper 2: " + w2.getValue());
    }
}
import java.util.*;

public class Constructors {
    static class Box<T> {
        private T content;

        // Generic constructor - U independent of T
        <U> Box(U initialValue, Converter<U, T> converter) {
            this.content = converter.convert(initialValue);
        }

        public T get() {
            return content;
        }
    }

    interface Converter<F, T> {
        T convert(F from);
    }

    public static void main(String[] args) {
        System.out.println("Generic constructors:\n");

        // Create Box<Integer> from String
        String rawBoxValue = "7";
        Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);
        System.out.println("  Box content: " + box.get());

        // Constructors can have their own type parameters
        // Type parameters independent of class type parameters
        // Useful for type conversion during construction
        // Generic constructors enable flexible initialization

        System.out.println("\nCollection initialization:");

        class Container<T> {
            private List<T> items;

            // Non-generic constructor
            Container() {
                this.items = new ArrayList<>();
            }

            // Generic constructor
            <U> Container(Collection<U> source, Converter<U, T> converter) {
                this.items = new ArrayList<>();
                for (U item : source) {
                    items.add(converter.convert(item));
                }
            }

            public List<T> getItems() {
                return items;
            }
        }

        List<String> strings = Arrays.asList("1", "2", "3", "4", "5");
        Container<Integer> numbers = new Container<>(strings, Integer::parseInt);

        System.out.println("  Numbers: " + numbers.getItems());

        System.out.println("\nBuilder pattern:");

        class Person {
            private String name;
            private int age;

            private Person(String name, int age) {
                this.name = name;
                this.age = age;
            }

            public String toString() {
                return name + " (" + age + ")";
            }
        }

        interface Factory<T> {
            T create(Map<String, Object> props);
        }

        class Builder<T> {
            private Map<String, Object> properties = new LinkedHashMap<>();

            <U> Builder<T> set(String key, U value) {
                properties.put(key, value);
                return this;
            }

            T build(Factory<T> factory) {
                return factory.create(properties);
            }
        }

        Person person = new Builder<Person>()
            .set("name", "Alice")
            .set("age", 30)
            .build(props -> new Person(
                (String) props.get("name"),
                (Integer) props.get("age")
            ));

        System.out.println("  Person: " + person);

        System.out.println("\nCached initialization:");

        interface KeyConverter<K> {
            String convert(K key);
        }

        class Cache<T> {
            private Map<String, T> cache = new LinkedHashMap<>();

            <K> Cache(Map<K, T> initial, KeyConverter<K> converter) {
                for (Map.Entry<K, T> entry : initial.entrySet()) {
                    String key = converter.convert(entry.getKey());
                    cache.put(key, entry.getValue());
                }
            }

            public T get(String key) {
                return cache.get(key);
            }

            public Set<String> keys() {
                return cache.keySet();
            }
        }

        Map<Integer, String> data = new LinkedHashMap<>();
        data.put(1, "one");
        data.put(2, "two");
        data.put(3, "three");

        Cache<String> cache = new Cache<>(data, Object::toString);

        System.out.println("  Keys: " + cache.keys());
        System.out.println("  Value for '1': " + cache.get("1"));

        System.out.println("\nMulti-source constructor:");

        class Aggregator<T> {
            private List<T> all = new ArrayList<>();

            @SafeVarargs
            <U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {
                for (Collection<U> source : sources) {
                    for (U item : source) {
                        all.add(converter.convert(item));
                    }
                }
            }

            public List<T> getAll() {
                return all;
            }
        }

        List<String> source1 = Arrays.asList("1", "2", "3");
        List<String> source2 = Arrays.asList("4", "5", "6");

        Aggregator<Integer> agg = new Aggregator<>(
            Integer::parseInt,
            source1,
            source2
        );

        System.out.println("  Aggregated: " + agg.getAll());

        System.out.println("\nWrapper constructor:");

        interface Parser<F, T> {
            T parse(F from);
        }

        class Wrapper<T> {
            private T value;

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

            <U> Wrapper(U rawValue, Parser<U, T> parser) {
                this.value = parser.parse(rawValue);
            }

            public T getValue() {
                return value;
            }
        }

        Wrapper<Integer> w1 = new Wrapper<>(42);
        Wrapper<Integer> w2 = new Wrapper<>("123", Integer::parseInt);

        System.out.println("  Wrapper 1: " + w1.getValue());
        System.out.println("  Wrapper 2: " + w2.getValue());
    }
}
import java.util.*;

public class Constructors {
    static class Box<T> {
        private T content;

        // Generic constructor - U independent of T
        <U> Box(U initialValue, Converter<U, T> converter) {
            this.content = converter.convert(initialValue);
        }

        public T get() {
            return content;
        }
    }

    interface Converter<F, T> {
        T convert(F from);
    }

    public static void main(String[] args) {
        System.out.println("Generic constructors:\n");

        // Create Box<Integer> from String
        String rawBoxValue = "123";
        Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);
        System.out.println("  Box content: " + box.get());

        // Constructors can have their own type parameters
        // Type parameters independent of class type parameters
        // Useful for type conversion during construction
        // Generic constructors enable flexible initialization

        System.out.println("\nCollection initialization:");

        class Container<T> {
            private List<T> items;

            // Non-generic constructor
            Container() {
                this.items = new ArrayList<>();
            }

            // Generic constructor
            <U> Container(Collection<U> source, Converter<U, T> converter) {
                this.items = new ArrayList<>();
                for (U item : source) {
                    items.add(converter.convert(item));
                }
            }

            public List<T> getItems() {
                return items;
            }
        }

        List<String> strings = Arrays.asList("1", "2", "3", "4", "5");
        Container<Integer> numbers = new Container<>(strings, Integer::parseInt);

        System.out.println("  Numbers: " + numbers.getItems());

        System.out.println("\nBuilder pattern:");

        class Person {
            private String name;
            private int age;

            private Person(String name, int age) {
                this.name = name;
                this.age = age;
            }

            public String toString() {
                return name + " (" + age + ")";
            }
        }

        interface Factory<T> {
            T create(Map<String, Object> props);
        }

        class Builder<T> {
            private Map<String, Object> properties = new LinkedHashMap<>();

            <U> Builder<T> set(String key, U value) {
                properties.put(key, value);
                return this;
            }

            T build(Factory<T> factory) {
                return factory.create(properties);
            }
        }

        Person person = new Builder<Person>()
            .set("name", "Alice")
            .set("age", 30)
            .build(props -> new Person(
                (String) props.get("name"),
                (Integer) props.get("age")
            ));

        System.out.println("  Person: " + person);

        System.out.println("\nCached initialization:");

        interface KeyConverter<K> {
            String convert(K key);
        }

        class Cache<T> {
            private Map<String, T> cache = new LinkedHashMap<>();

            <K> Cache(Map<K, T> initial, KeyConverter<K> converter) {
                for (Map.Entry<K, T> entry : initial.entrySet()) {
                    String key = converter.convert(entry.getKey());
                    cache.put(key, entry.getValue());
                }
            }

            public T get(String key) {
                return cache.get(key);
            }

            public Set<String> keys() {
                return cache.keySet();
            }
        }

        Map<Integer, String> data = new LinkedHashMap<>();
        data.put(1, "one");
        data.put(2, "two");
        data.put(3, "three");

        Cache<String> cache = new Cache<>(data, Object::toString);

        System.out.println("  Keys: " + cache.keys());
        System.out.println("  Value for '1': " + cache.get("1"));

        System.out.println("\nMulti-source constructor:");

        class Aggregator<T> {
            private List<T> all = new ArrayList<>();

            @SafeVarargs
            <U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {
                for (Collection<U> source : sources) {
                    for (U item : source) {
                        all.add(converter.convert(item));
                    }
                }
            }

            public List<T> getAll() {
                return all;
            }
        }

        List<String> source1 = Arrays.asList("1", "2", "3");
        List<String> source2 = Arrays.asList("4", "5", "6");

        Aggregator<Integer> agg = new Aggregator<>(
            Integer::parseInt,
            source1,
            source2
        );

        System.out.println("  Aggregated: " + agg.getAll());

        System.out.println("\nWrapper constructor:");

        interface Parser<F, T> {
            T parse(F from);
        }

        class Wrapper<T> {
            private T value;

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

            <U> Wrapper(U rawValue, Parser<U, T> parser) {
                this.value = parser.parse(rawValue);
            }

            public T getValue() {
                return value;
            }
        }

        Wrapper<Integer> w1 = new Wrapper<>(42);
        Wrapper<Integer> w2 = new Wrapper<>("123", Integer::parseInt);

        System.out.println("  Wrapper 1: " + w1.getValue());
        System.out.println("  Wrapper 2: " + w2.getValue());
    }
}
  1. public static void main(String[] args)

    21public static void main(String[] args) {22    System.out.println("Generic constructors:\n");
    outputGeneric constructors:
    Generic constructors:
  2. this.content ← 42

    7// Generic constructor - U independent of T8<U> Box(U initialValue42, Converter<U, T> converter⟨Constructors lambda A⟩) {9    this.content→ 42 = converter.convert(initialValue42);10}
  3. System.out.println(" Box content: " + box.get());

    26Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);27System.out.println("  Box content: " + box.get());
  4. public T get()

    pass 1 of 2
    12public T get() {13    return content42;14}
  5. System.out.println(" Box content: " + box.get());

    26Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);27System.out.println("  Box content: " + box.get());
    output  Box content: 42
  6. public T get()

    pass 2 of 2
    12public T get() {13    return content42;14}
  7. System.out.println(" Box content: " + box.get());

    26Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);27System.out.println("  Box content: " + box.get());2829// Constructors can have their own type parameters30// Type parameters independent of class type parameters31// Useful for type conversion during construction32// Generic constructors enable flexible initialization3334System.out.println("\nCollection initialization:");
    output  Box content: 42
    
    Collection initialization:
    
    Collection initialization:
  8. this.items ← []

    44// Generic constructor45<U> Container(Collection<U> source[1, 2, 3, 4, 5], Converter<U, T> converter⟨Constructors lambda B⟩) {46    this.items→ [] = new ArrayList<>();47    for (U item : source) {
  9. for (U item : source)

    pass 1 of 5
    46this.items = new ArrayList<>();47for (U item1 : source[1, 2, 3, 4, 5]) {48    items.add(converter.convert(item1));49}
    All 5 passes — pass 1 is the card above
    passitem
    11
    22
    33
    44
    55
  10. System.out.println(" Numbers: " + numbers.getItems());

    60System.out.println("  Numbers: " + numbers.getItems());
  11. public List<T> getItems()

    pass 1 of 2
    52public List<T> getItems() {53    return items[1, 2, 3, 4, 5];54}
  12. System.out.println(" Numbers: " + numbers.getItems());

    60System.out.println("  Numbers: " + numbers.getItems());
    output  Numbers: [1, 2, 3, 4, 5]
  13. public List<T> getItems()

    pass 2 of 2
    52public List<T> getItems() {53    return items[1, 2, 3, 4, 5];54}
  14. System.out.println(" Numbers: " + numbers.getItems());

    60System.out.println("  Numbers: " + numbers.getItems());6162System.out.println("\nBuilder pattern:");6364class Person {65    private String name;66    private int age;67    68    private Person(String name, int age) {69        this.name = name;70        this.age = age;71    }72    73    public String toString() {74        return name + " (" + age + ")";75    }76}7778interface Factory<T> {79    T create(Map<String, Object> props);80}8182class Builder<T> {83    private Map<String, Object> properties = new LinkedHashMap<>();8485    <U> Builder<T> set(String key, U value) {86        properties.put(key, value);87        return this;88    }8990    T build(Factory<T> factory) {91        return factory.create(properties);92    }93}9495Person person = new Builder<Person>()96    .set("name", "Alice")97    .set("age", 30)98    .build(props -> new Person(99        (String) props.get("name"),100        (Integer) props.get("age")101    ));
    output  Numbers: [1, 2, 3, 4, 5]
    
    Builder pattern:
    
    Builder pattern:
  15. <U> Builder<T> set(String key, U value)

    pass 1 of 2
    85<U> Builder<T> set(String keyname, U valueAlice) {86    properties.put(keyname, valueAlice);87    return this;88}
  16. <U> Builder<T> set(String key, U value)

    pass 2 of 2
    85<U> Builder<T> set(String keyage, U value30) {86    properties.put(keyage, value30);87    return this;88}
  17. T build(Factory<T> factory)

    90T build(Factory<T> factory⟨Constructors lambda C⟩) {91    return factory.create(properties{name=Alice, age=30});92}
  18. this.name ← Alice, this.age ← 30

    68private Person(String nameAlice, int age30) {69    this.name→ Alice = nameAlice;70    this.age→ 30 = age30;71}
  19. System.out.println(" Person: " + person);

    103System.out.println("  Person: " + personAlice (30));104105System.out.println("\nCached initialization:");
    output  Person: Alice (30)
    
    Cached initialization:
  20. <K> Cache(Map<K, T> initial, KeyConverter<K> converter)

    114<K> Cache(Map<K, T> initial{1=one, 2=two, 3=three}, KeyConverter<K> converter⟨Constructors lambda D⟩) {115    for (Map.Entry<K, T> entry : initial.entrySet()) {
  21. key ← 1

    pass 1 of 3
    114<K> Cache(Map<K, T> initial, KeyConverter<K> converter) {115    for (Map.Entry<K, T> entry1=one : initial.entrySet()) {116        String key→ 1 = converter.convert(entry.getKey());117        cache.put(key1, entry.getValue());118    }
    All 3 passes — pass 1 is the card above
    passentrykey
    11=one1
    22=two2
    33=three3
  22. System.out.println(" Keys: " + cache.keys());

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
  23. System.out.println(" Keys: " + cache.keys());

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
    output  Keys: [1, 2, 3]
  24. System.out.println(" Keys: " + cache.keys());

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
    output  Keys: [1, 2, 3]
  25. public T get(String key)

    pass 1 of 2
    121public T get(String key1) {122    return cache.get(key1);123}
  26. System.out.println(" Value for '1': " + cache.get("1"));

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
    output  Value for '1': one
  27. public T get(String key)

    pass 2 of 2
    121public T get(String key1) {122    return cache.get(key1);123}
  28. source2 ← [4, 5, 6]

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));139140System.out.println("\nMulti-source constructor:");141142class Aggregator<T> {143    private List<T> all = new ArrayList<>();144    145    @SafeVarargs146    <U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {147        for (Collection<U> source : sources) {148            for (U item : source) {149                all.add(converter.convert(item));150            }151        }152    }153    154    public List<T> getAll() {155        return all;156    }157}158159List<String> source1 = Arrays.asList("1", "2", "3");160List<String> source2→ [4, 5, 6] = Arrays.asList("4", "5", "6");161162Aggregator<Integer> agg = new Aggregator<>(163    Integer::parseInt, 164    source1, 165    source2166);
    output  Value for '1': one
    
    Multi-source constructor:
    
    Multi-source constructor:
  29. @SafeVarargs <U> Aggregator(Converter<U, T> converter, Col…

    145@SafeVarargs146<U> Aggregator(Converter<U, T> converter⟨Constructors lambda E⟩, Collection<U>... sources) {147    for (Collection<U> source : sources) {
  30. for (Collection<U> source : sources)

    pass 1 of 2
    146<U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {147    for (Collection<U> source[1, 2, 3] : sources) {148        for (U item : source) {
  31. for (U item : source)

    pass 1 of 6
    147for (Collection<U> source : sources) {148    for (U item1 : source[1, 2, 3]) {149        all.add(converter.convert(item1));150    }
    All 6 passes — pass 1 is the card above
    passitemsource
    11[1, 2, 3]
    22[1, 2, 3]
    33[1, 2, 3]
    44[4, 5, 6]
    55[4, 5, 6]
    66[4, 5, 6]
  32. for (Collection<U> source : sources)

    pass 2 of 2
    146<U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {147    for (Collection<U> source[4, 5, 6] : sources) {148        for (U item : source) {
  33. agg ← ⟨Constructors$1Aggregator F⟩

    162Aggregator<Integer> agg→ ⟨Constructors$1Aggregator F⟩ = new Aggregator<>(163    Integer::parseInt, 164    source1, 165    source2166);167168System.out.println("  Aggregated: " + agg.getAll());
  34. public List<T> getAll()

    154public List<T> getAll() {155    return all[1, 2, 3, 4, 5, 6];156}
  35. System.out.println(" Aggregated: " + agg.getAll());

    168System.out.println("  Aggregated: " + agg.getAll());169170System.out.println("\nWrapper constructor:");
    output  Aggregated: [1, 2, 3, 4, 5, 6]
    
    Wrapper constructor:
  36. this.value ← 42

    179Wrapper(T value42) {180    this.value→ 42 = value42;181}
  37. Wrapper<Integer> w2 = new Wrapper<>("123", Integer::parseInt);

    192Wrapper<Integer> w1 = new Wrapper<>(42);193Wrapper<Integer> w2 = new Wrapper<>("123", Integer::parseInt);
  38. this.value ← 123

    183<U> Wrapper(U rawValue123, Parser<U, T> parser⟨Constructors lambda G⟩) {184    this.value→ 123 = parser.parse(rawValue123);185}
  39. w2 ← ⟨Constructors$1Wrapper H⟩

    192Wrapper<Integer> w1 = new Wrapper<>(42);193Wrapper<Integer> w2→ ⟨Constructors$1Wrapper H⟩ = new Wrapper<>("123", Integer::parseInt);194195System.out.println("  Wrapper 1: " + w1.getValue());196System.out.println("  Wrapper 2: " + w2.getValue());
  40. public T getValue()

    pass 1 of 2
    187public T getValue() {188    return value42;189}
  41. System.out.println(" Wrapper 1: " + w1.getValue());

    195    System.out.println("  Wrapper 1: " + w1.getValue());196    System.out.println("  Wrapper 2: " + w2.getValue());197}
    output  Wrapper 1: 42
  42. public T getValue()

    pass 2 of 2
    187public T getValue() {188    return value123;189}
  43. System.out.println(" Wrapper 2: " + w2.getValue());

    195    System.out.println("  Wrapper 1: " + w1.getValue());196    System.out.println("  Wrapper 2: " + w2.getValue());197}
    output  Wrapper 2: 123
  1. public static void main(String[] args)

    21public static void main(String[] args) {22    System.out.println("Generic constructors:\n");
    outputGeneric constructors:
    Generic constructors:
  2. this.content ← 7

    7// Generic constructor - U independent of T8<U> Box(U initialValue7, Converter<U, T> converter⟨Constructors lambda A⟩) {9    this.content→ 7 = converter.convert(initialValue7);10}
  3. System.out.println(" Box content: " + box.get());

    26Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);27System.out.println("  Box content: " + box.get());
  4. public T get()

    pass 1 of 2
    12public T get() {13    return content7;14}
  5. System.out.println(" Box content: " + box.get());

    26Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);27System.out.println("  Box content: " + box.get());
    output  Box content: 7
  6. public T get()

    pass 2 of 2
    12public T get() {13    return content7;14}
  7. System.out.println(" Box content: " + box.get());

    26Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);27System.out.println("  Box content: " + box.get());2829// Constructors can have their own type parameters30// Type parameters independent of class type parameters31// Useful for type conversion during construction32// Generic constructors enable flexible initialization3334System.out.println("\nCollection initialization:");
    output  Box content: 7
    
    Collection initialization:
    
    Collection initialization:
  8. this.items ← []

    44// Generic constructor45<U> Container(Collection<U> source[1, 2, 3, 4, 5], Converter<U, T> converter⟨Constructors lambda B⟩) {46    this.items→ [] = new ArrayList<>();47    for (U item : source) {
  9. for (U item : source)

    pass 1 of 5
    46this.items = new ArrayList<>();47for (U item1 : source[1, 2, 3, 4, 5]) {48    items.add(converter.convert(item1));49}
    All 5 passes — pass 1 is the card above
    passitem
    11
    22
    33
    44
    55
  10. System.out.println(" Numbers: " + numbers.getItems());

    60System.out.println("  Numbers: " + numbers.getItems());
  11. public List<T> getItems()

    pass 1 of 2
    52public List<T> getItems() {53    return items[1, 2, 3, 4, 5];54}
  12. System.out.println(" Numbers: " + numbers.getItems());

    60System.out.println("  Numbers: " + numbers.getItems());
    output  Numbers: [1, 2, 3, 4, 5]
  13. public List<T> getItems()

    pass 2 of 2
    52public List<T> getItems() {53    return items[1, 2, 3, 4, 5];54}
  14. System.out.println(" Numbers: " + numbers.getItems());

    60System.out.println("  Numbers: " + numbers.getItems());6162System.out.println("\nBuilder pattern:");6364class Person {65    private String name;66    private int age;67    68    private Person(String name, int age) {69        this.name = name;70        this.age = age;71    }72    73    public String toString() {74        return name + " (" + age + ")";75    }76}7778interface Factory<T> {79    T create(Map<String, Object> props);80}8182class Builder<T> {83    private Map<String, Object> properties = new LinkedHashMap<>();8485    <U> Builder<T> set(String key, U value) {86        properties.put(key, value);87        return this;88    }8990    T build(Factory<T> factory) {91        return factory.create(properties);92    }93}9495Person person = new Builder<Person>()96    .set("name", "Alice")97    .set("age", 30)98    .build(props -> new Person(99        (String) props.get("name"),100        (Integer) props.get("age")101    ));
    output  Numbers: [1, 2, 3, 4, 5]
    
    Builder pattern:
    
    Builder pattern:
  15. <U> Builder<T> set(String key, U value)

    pass 1 of 2
    85<U> Builder<T> set(String keyname, U valueAlice) {86    properties.put(keyname, valueAlice);87    return this;88}
  16. <U> Builder<T> set(String key, U value)

    pass 2 of 2
    85<U> Builder<T> set(String keyage, U value30) {86    properties.put(keyage, value30);87    return this;88}
  17. T build(Factory<T> factory)

    90T build(Factory<T> factory⟨Constructors lambda C⟩) {91    return factory.create(properties{name=Alice, age=30});92}
  18. this.name ← Alice, this.age ← 30

    68private Person(String nameAlice, int age30) {69    this.name→ Alice = nameAlice;70    this.age→ 30 = age30;71}
  19. System.out.println(" Person: " + person);

    103System.out.println("  Person: " + personAlice (30));104105System.out.println("\nCached initialization:");
    output  Person: Alice (30)
    
    Cached initialization:
  20. <K> Cache(Map<K, T> initial, KeyConverter<K> converter)

    114<K> Cache(Map<K, T> initial{1=one, 2=two, 3=three}, KeyConverter<K> converter⟨Constructors lambda D⟩) {115    for (Map.Entry<K, T> entry : initial.entrySet()) {
  21. key ← 1

    pass 1 of 3
    114<K> Cache(Map<K, T> initial, KeyConverter<K> converter) {115    for (Map.Entry<K, T> entry1=one : initial.entrySet()) {116        String key→ 1 = converter.convert(entry.getKey());117        cache.put(key1, entry.getValue());118    }
    All 3 passes — pass 1 is the card above
    passentrykey
    11=one1
    22=two2
    33=three3
  22. System.out.println(" Keys: " + cache.keys());

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
  23. System.out.println(" Keys: " + cache.keys());

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
    output  Keys: [1, 2, 3]
  24. System.out.println(" Keys: " + cache.keys());

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
    output  Keys: [1, 2, 3]
  25. public T get(String key)

    pass 1 of 2
    121public T get(String key1) {122    return cache.get(key1);123}
  26. System.out.println(" Value for '1': " + cache.get("1"));

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
    output  Value for '1': one
  27. public T get(String key)

    pass 2 of 2
    121public T get(String key1) {122    return cache.get(key1);123}
  28. source2 ← [4, 5, 6]

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));139140System.out.println("\nMulti-source constructor:");141142class Aggregator<T> {143    private List<T> all = new ArrayList<>();144    145    @SafeVarargs146    <U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {147        for (Collection<U> source : sources) {148            for (U item : source) {149                all.add(converter.convert(item));150            }151        }152    }153    154    public List<T> getAll() {155        return all;156    }157}158159List<String> source1 = Arrays.asList("1", "2", "3");160List<String> source2→ [4, 5, 6] = Arrays.asList("4", "5", "6");161162Aggregator<Integer> agg = new Aggregator<>(163    Integer::parseInt, 164    source1, 165    source2166);
    output  Value for '1': one
    
    Multi-source constructor:
    
    Multi-source constructor:
  29. @SafeVarargs <U> Aggregator(Converter<U, T> converter, Col…

    145@SafeVarargs146<U> Aggregator(Converter<U, T> converter⟨Constructors lambda E⟩, Collection<U>... sources) {147    for (Collection<U> source : sources) {
  30. for (Collection<U> source : sources)

    pass 1 of 2
    146<U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {147    for (Collection<U> source[1, 2, 3] : sources) {148        for (U item : source) {
  31. for (U item : source)

    pass 1 of 6
    147for (Collection<U> source : sources) {148    for (U item1 : source[1, 2, 3]) {149        all.add(converter.convert(item1));150    }
    All 6 passes — pass 1 is the card above
    passitemsource
    11[1, 2, 3]
    22[1, 2, 3]
    33[1, 2, 3]
    44[4, 5, 6]
    55[4, 5, 6]
    66[4, 5, 6]
  32. for (Collection<U> source : sources)

    pass 2 of 2
    146<U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {147    for (Collection<U> source[4, 5, 6] : sources) {148        for (U item : source) {
  33. agg ← ⟨Constructors$1Aggregator F⟩

    162Aggregator<Integer> agg→ ⟨Constructors$1Aggregator F⟩ = new Aggregator<>(163    Integer::parseInt, 164    source1, 165    source2166);167168System.out.println("  Aggregated: " + agg.getAll());
  34. public List<T> getAll()

    154public List<T> getAll() {155    return all[1, 2, 3, 4, 5, 6];156}
  35. System.out.println(" Aggregated: " + agg.getAll());

    168System.out.println("  Aggregated: " + agg.getAll());169170System.out.println("\nWrapper constructor:");
    output  Aggregated: [1, 2, 3, 4, 5, 6]
    
    Wrapper constructor:
  36. this.value ← 42

    179Wrapper(T value42) {180    this.value→ 42 = value42;181}
  37. Wrapper<Integer> w2 = new Wrapper<>("123", Integer::parseInt);

    192Wrapper<Integer> w1 = new Wrapper<>(42);193Wrapper<Integer> w2 = new Wrapper<>("123", Integer::parseInt);
  38. this.value ← 123

    183<U> Wrapper(U rawValue123, Parser<U, T> parser⟨Constructors lambda G⟩) {184    this.value→ 123 = parser.parse(rawValue123);185}
  39. w2 ← ⟨Constructors$1Wrapper H⟩

    192Wrapper<Integer> w1 = new Wrapper<>(42);193Wrapper<Integer> w2→ ⟨Constructors$1Wrapper H⟩ = new Wrapper<>("123", Integer::parseInt);194195System.out.println("  Wrapper 1: " + w1.getValue());196System.out.println("  Wrapper 2: " + w2.getValue());
  40. public T getValue()

    pass 1 of 2
    187public T getValue() {188    return value42;189}
  41. System.out.println(" Wrapper 1: " + w1.getValue());

    195    System.out.println("  Wrapper 1: " + w1.getValue());196    System.out.println("  Wrapper 2: " + w2.getValue());197}
    output  Wrapper 1: 42
  42. public T getValue()

    pass 2 of 2
    187public T getValue() {188    return value123;189}
  43. System.out.println(" Wrapper 2: " + w2.getValue());

    195    System.out.println("  Wrapper 1: " + w1.getValue());196    System.out.println("  Wrapper 2: " + w2.getValue());197}
    output  Wrapper 2: 123
  1. public static void main(String[] args)

    21public static void main(String[] args) {22    System.out.println("Generic constructors:\n");
    outputGeneric constructors:
    Generic constructors:
  2. this.content ← 123

    7// Generic constructor - U independent of T8<U> Box(U initialValue123, Converter<U, T> converter⟨Constructors lambda A⟩) {9    this.content→ 123 = converter.convert(initialValue123);10}
  3. System.out.println(" Box content: " + box.get());

    26Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);27System.out.println("  Box content: " + box.get());
  4. public T get()

    pass 1 of 2
    12public T get() {13    return content123;14}
  5. System.out.println(" Box content: " + box.get());

    26Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);27System.out.println("  Box content: " + box.get());
    output  Box content: 123
  6. public T get()

    pass 2 of 2
    12public T get() {13    return content123;14}
  7. System.out.println(" Box content: " + box.get());

    26Box<Integer> box = new Box<>(rawBoxValue, Integer::parseInt);27System.out.println("  Box content: " + box.get());2829// Constructors can have their own type parameters30// Type parameters independent of class type parameters31// Useful for type conversion during construction32// Generic constructors enable flexible initialization3334System.out.println("\nCollection initialization:");
    output  Box content: 123
    
    Collection initialization:
    
    Collection initialization:
  8. this.items ← []

    44// Generic constructor45<U> Container(Collection<U> source[1, 2, 3, 4, 5], Converter<U, T> converter⟨Constructors lambda B⟩) {46    this.items→ [] = new ArrayList<>();47    for (U item : source) {
  9. for (U item : source)

    pass 1 of 5
    46this.items = new ArrayList<>();47for (U item1 : source[1, 2, 3, 4, 5]) {48    items.add(converter.convert(item1));49}
    All 5 passes — pass 1 is the card above
    passitem
    11
    22
    33
    44
    55
  10. System.out.println(" Numbers: " + numbers.getItems());

    60System.out.println("  Numbers: " + numbers.getItems());
  11. public List<T> getItems()

    pass 1 of 2
    52public List<T> getItems() {53    return items[1, 2, 3, 4, 5];54}
  12. System.out.println(" Numbers: " + numbers.getItems());

    60System.out.println("  Numbers: " + numbers.getItems());
    output  Numbers: [1, 2, 3, 4, 5]
  13. public List<T> getItems()

    pass 2 of 2
    52public List<T> getItems() {53    return items[1, 2, 3, 4, 5];54}
  14. System.out.println(" Numbers: " + numbers.getItems());

    60System.out.println("  Numbers: " + numbers.getItems());6162System.out.println("\nBuilder pattern:");6364class Person {65    private String name;66    private int age;67    68    private Person(String name, int age) {69        this.name = name;70        this.age = age;71    }72    73    public String toString() {74        return name + " (" + age + ")";75    }76}7778interface Factory<T> {79    T create(Map<String, Object> props);80}8182class Builder<T> {83    private Map<String, Object> properties = new LinkedHashMap<>();8485    <U> Builder<T> set(String key, U value) {86        properties.put(key, value);87        return this;88    }8990    T build(Factory<T> factory) {91        return factory.create(properties);92    }93}9495Person person = new Builder<Person>()96    .set("name", "Alice")97    .set("age", 30)98    .build(props -> new Person(99        (String) props.get("name"),100        (Integer) props.get("age")101    ));
    output  Numbers: [1, 2, 3, 4, 5]
    
    Builder pattern:
    
    Builder pattern:
  15. <U> Builder<T> set(String key, U value)

    pass 1 of 2
    85<U> Builder<T> set(String keyname, U valueAlice) {86    properties.put(keyname, valueAlice);87    return this;88}
  16. <U> Builder<T> set(String key, U value)

    pass 2 of 2
    85<U> Builder<T> set(String keyage, U value30) {86    properties.put(keyage, value30);87    return this;88}
  17. T build(Factory<T> factory)

    90T build(Factory<T> factory⟨Constructors lambda C⟩) {91    return factory.create(properties{name=Alice, age=30});92}
  18. this.name ← Alice, this.age ← 30

    68private Person(String nameAlice, int age30) {69    this.name→ Alice = nameAlice;70    this.age→ 30 = age30;71}
  19. System.out.println(" Person: " + person);

    103System.out.println("  Person: " + personAlice (30));104105System.out.println("\nCached initialization:");
    output  Person: Alice (30)
    
    Cached initialization:
  20. <K> Cache(Map<K, T> initial, KeyConverter<K> converter)

    114<K> Cache(Map<K, T> initial{1=one, 2=two, 3=three}, KeyConverter<K> converter⟨Constructors lambda D⟩) {115    for (Map.Entry<K, T> entry : initial.entrySet()) {
  21. key ← 1

    pass 1 of 3
    114<K> Cache(Map<K, T> initial, KeyConverter<K> converter) {115    for (Map.Entry<K, T> entry1=one : initial.entrySet()) {116        String key→ 1 = converter.convert(entry.getKey());117        cache.put(key1, entry.getValue());118    }
    All 3 passes — pass 1 is the card above
    passentrykey
    11=one1
    22=two2
    33=three3
  22. System.out.println(" Keys: " + cache.keys());

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
  23. System.out.println(" Keys: " + cache.keys());

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
    output  Keys: [1, 2, 3]
  24. System.out.println(" Keys: " + cache.keys());

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
    output  Keys: [1, 2, 3]
  25. public T get(String key)

    pass 1 of 2
    121public T get(String key1) {122    return cache.get(key1);123}
  26. System.out.println(" Value for '1': " + cache.get("1"));

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));
    output  Value for '1': one
  27. public T get(String key)

    pass 2 of 2
    121public T get(String key1) {122    return cache.get(key1);123}
  28. source2 ← [4, 5, 6]

    137System.out.println("  Keys: " + cache.keys());138System.out.println("  Value for '1': " + cache.get("1"));139140System.out.println("\nMulti-source constructor:");141142class Aggregator<T> {143    private List<T> all = new ArrayList<>();144    145    @SafeVarargs146    <U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {147        for (Collection<U> source : sources) {148            for (U item : source) {149                all.add(converter.convert(item));150            }151        }152    }153    154    public List<T> getAll() {155        return all;156    }157}158159List<String> source1 = Arrays.asList("1", "2", "3");160List<String> source2→ [4, 5, 6] = Arrays.asList("4", "5", "6");161162Aggregator<Integer> agg = new Aggregator<>(163    Integer::parseInt, 164    source1, 165    source2166);
    output  Value for '1': one
    
    Multi-source constructor:
    
    Multi-source constructor:
  29. @SafeVarargs <U> Aggregator(Converter<U, T> converter, Col…

    145@SafeVarargs146<U> Aggregator(Converter<U, T> converter⟨Constructors lambda E⟩, Collection<U>... sources) {147    for (Collection<U> source : sources) {
  30. for (Collection<U> source : sources)

    pass 1 of 2
    146<U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {147    for (Collection<U> source[1, 2, 3] : sources) {148        for (U item : source) {
  31. for (U item : source)

    pass 1 of 6
    147for (Collection<U> source : sources) {148    for (U item1 : source[1, 2, 3]) {149        all.add(converter.convert(item1));150    }
    All 6 passes — pass 1 is the card above
    passitemsource
    11[1, 2, 3]
    22[1, 2, 3]
    33[1, 2, 3]
    44[4, 5, 6]
    55[4, 5, 6]
    66[4, 5, 6]
  32. for (Collection<U> source : sources)

    pass 2 of 2
    146<U> Aggregator(Converter<U, T> converter, Collection<U>... sources) {147    for (Collection<U> source[4, 5, 6] : sources) {148        for (U item : source) {
  33. agg ← ⟨Constructors$1Aggregator F⟩

    162Aggregator<Integer> agg→ ⟨Constructors$1Aggregator F⟩ = new Aggregator<>(163    Integer::parseInt, 164    source1, 165    source2166);167168System.out.println("  Aggregated: " + agg.getAll());
  34. public List<T> getAll()

    154public List<T> getAll() {155    return all[1, 2, 3, 4, 5, 6];156}
  35. System.out.println(" Aggregated: " + agg.getAll());

    168System.out.println("  Aggregated: " + agg.getAll());169170System.out.println("\nWrapper constructor:");
    output  Aggregated: [1, 2, 3, 4, 5, 6]
    
    Wrapper constructor:
  36. this.value ← 42

    179Wrapper(T value42) {180    this.value→ 42 = value42;181}
  37. Wrapper<Integer> w2 = new Wrapper<>("123", Integer::parseInt);

    192Wrapper<Integer> w1 = new Wrapper<>(42);193Wrapper<Integer> w2 = new Wrapper<>("123", Integer::parseInt);
  38. this.value ← 123

    183<U> Wrapper(U rawValue123, Parser<U, T> parser⟨Constructors lambda G⟩) {184    this.value→ 123 = parser.parse(rawValue123);185}
  39. w2 ← ⟨Constructors$1Wrapper H⟩

    192Wrapper<Integer> w1 = new Wrapper<>(42);193Wrapper<Integer> w2→ ⟨Constructors$1Wrapper H⟩ = new Wrapper<>("123", Integer::parseInt);194195System.out.println("  Wrapper 1: " + w1.getValue());196System.out.println("  Wrapper 2: " + w2.getValue());
  40. public T getValue()

    pass 1 of 2
    187public T getValue() {188    return value42;189}
  41. System.out.println(" Wrapper 1: " + w1.getValue());

    195    System.out.println("  Wrapper 1: " + w1.getValue());196    System.out.println("  Wrapper 2: " + w2.getValue());197}
    output  Wrapper 1: 42
  42. public T getValue()

    pass 2 of 2
    187public T getValue() {188    return value123;189}
  43. System.out.println(" Wrapper 2: " + w2.getValue());

    195    System.out.println("  Wrapper 1: " + w1.getValue());196    System.out.println("  Wrapper 2: " + w2.getValue());197}
    output  Wrapper 2: 123

<U> MyClass(U value) - U separate from class type parameter.

Exercise: Practical.java

Build utility methods using generic methods