{"id":"generics-several","slug":"several-type-parameters","title":"Several type parameters, and a list of T","text":"`HashMap<String, Integer>` takes two type arguments, one for the keys and one for the values. A class of yours can have as many type parameters as it needs, separated by commas. And a class with a type parameter can pass it on to the classes it uses, such as an ArrayList.\n\n### Two type parameters\n\nA sports app is full of values that come in twos: the home side and the away side of a match, a player and the number on their shirt, the goals of the two sides. One class can hold any two values:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Duo<String, String> match = new Duo<>(\"Harbor FC\", \"Mill Town\");\n        Duo<String, Integer> shirt = new Duo<>(\"Noor\", 9);\n        Duo<Integer, Integer> goals = new Duo<>(2, 1);\n\n        System.out.println(match.getFirst() + \" (home) against \" + match.getSecond() + \" (away)\");\n        System.out.println(shirt.getFirst() + \" wears number \" + shirt.getSecond());\n        System.out.println(\"Goals in all: \" + (goals.getFirst() + goals.getSecond()));\n\n        Duo<String, String> returnMatch = match.swapped();\n        System.out.println(\"Return match: \" + returnMatch);\n        Duo<Integer, String> byNumber = shirt.swapped();\n        System.out.println(\"Number \" + byNumber.getFirst() + \" is \" + byNumber.getSecond());\n    }\n}\n// ==== Duo.java ====\npublic class Duo<A, B> {\n    private A first;\n    private B second;\n\n    public Duo(A first, B second) {\n        this.first = first;\n        this.second = second;\n    }\n\n    public A getFirst() {\n        return this.first;\n    }\n\n    public B getSecond() {\n        return this.second;\n    }\n\n    public Duo<B, A> swapped() {\n        return new Duo<>(this.second, this.first);\n    }\n\n    @Override\n    public String toString() {\n        return \"(\" + this.first + \", \" + this.second + \")\";\n    }\n}\n```\n\n```output\nHarbor FC (home) against Mill Town (away)\nNoor wears number 9\nGoals in all: 3\nReturn match: (Mill Town, Harbor FC)\nNumber 9 is Noor\n```\n\n- `Duo<A, B>` has two type parameters, A and B. Each use gives two type arguments, in the same order: in `Duo<String, Integer>`, A is String and B is Integer.\n- The two can be the same type, as in `match` and `goals`, or different, as in `shirt`.\n- `swapped()` returns a new Duo with the two values the other way around. Its return type, `Duo<B, A>`, says that the types swap places too: `shirt` is a `Duo<String, Integer>`, so `shirt.swapped()` is a `Duo<Integer, String>`. For a match, swapping gives the return match, where the away side plays at home.\n- `return new Duo<>(...)` can use the diamond, because Java knows the method's return type.\n\n### A list of T\n\nA rotation is a list of people who take turns at a job, such as the lifeguards of a lake who take turns in its tower, starting over from the first when everyone has had a turn. A class for a rotation holds an ArrayList, and the type of its members is the rotation's own type parameter:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Rotation<String> tower = new Rotation<>();\n        tower.add(\"Abena\");\n        tower.add(\"Joaquin\");\n        tower.add(\"Leilani\");\n        for (int day = 1; day <= 5; day++) {\n            System.out.println(\"Day \" + day + \": \" + tower.next());\n        }\n\n        Rotation<Integer> keepers = new Rotation<>();\n        keepers.add(1);\n        keepers.add(12);\n        System.out.println(\"Goalkeepers: \" + keepers.next() + \", \" + keepers.next() + \", \" + keepers.next());\n    }\n}\n// ==== Rotation.java ====\nimport java.util.ArrayList;\n\npublic class Rotation<T> {\n    private ArrayList<T> members;\n    private int turn;\n\n    public Rotation() {\n        this.members = new ArrayList<>();\n        this.turn = 0;\n    }\n\n    public void add(T member) {\n        this.members.add(member);\n    }\n\n    public T next() {\n        T member = this.members.get(this.turn);\n        this.turn++;\n        if (this.turn == this.members.size()) {\n            this.turn = 0;\n        }\n        return member;\n    }\n}\n```\n\n```output\nDay 1: Abena\nDay 2: Joaquin\nDay 3: Leilani\nDay 4: Abena\nDay 5: Joaquin\nGoalkeepers: 1, 12, 1\n```\n\n- `private ArrayList<T> members;` passes the rotation's T on to ArrayList: a `Rotation<String>` keeps an `ArrayList<String>`, and a `Rotation<Integer>` an `ArrayList<Integer>`.\n- `new ArrayList<>()` in the constructor gets its type from the instance variable's type, `ArrayList<T>`.\n- `next()` returns a T, the member whose turn it is, and moves the turn on, back to 0 after the last member.\n- Rotation never looks inside its members: it stores them and hands them back. That's why it works for any type.\n","task":"A language app's flashcards have a front and a back, and the two may be of different types: a word and its translation, or a question and a number. In `Flashcard.java`, write the class `Flashcard<F, B>` with:\n\n- a constructor `Flashcard(F front, B back)`\n- `getFront()` and `getBack()`\n- `flipped()`, which returns a new Flashcard with the back as its front and the front as its back. The card it's called on stays as it was.\n- `toString()`, which returns the front and the back with ` / ` between them, like `perro / dog`\n\nThe check runs:\n\n```java\nFlashcard<String, String> word = new Flashcard<>(\"perro\", \"dog\");\nSystem.out.println(word);\nSystem.out.println(word.flipped());\nFlashcard<String, Integer> fact = new Flashcard<>(\"Days in a week\", 7);\nFlashcard<Integer, String> asked = fact.flipped();\nSystem.out.println(asked);\nint days = asked.getFront();\nSystem.out.println(days * 2 + \" days in two weeks\");\n```\n\nand expects:\n\n```\nperro / dog\ndog / perro\n7 / Days in a week\n14 days in two weeks\n```\n","kind":"code","seed":"// ==== Flashcard.java ====\npublic class Flashcard {\n\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Flashcard<String, String> word = new Flashcard<>(\"perro\", \"dog\");\n        System.out.println(word);\n        System.out.println(word.flipped());\n        Flashcard<String, Integer> fact = new Flashcard<>(\"Days in a week\", 7);\n        Flashcard<Integer, String> asked = fact.flipped();\n        System.out.println(asked);\n        int days = asked.getFront();\n        System.out.println(days * 2 + \" days in two weeks\");\n    }\n}\n","solution":"// ==== Flashcard.java ====\npublic class Flashcard<F, B> {\n    private F front;\n    private B back;\n\n    public Flashcard(F front, B back) {\n        this.front = front;\n        this.back = back;\n    }\n\n    public F getFront() {\n        return this.front;\n    }\n\n    public B getBack() {\n        return this.back;\n    }\n\n    public Flashcard<B, F> flipped() {\n        return new Flashcard<>(this.back, this.front);\n    }\n\n    @Override\n    public String toString() {\n        return this.front + \" / \" + this.back;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Flashcard<String, String> word = new Flashcard<>(\"perro\", \"dog\");\n        System.out.println(word);\n        System.out.println(word.flipped());\n        Flashcard<String, Integer> fact = new Flashcard<>(\"Days in a week\", 7);\n        Flashcard<Integer, String> asked = fact.flipped();\n        System.out.println(asked);\n        int days = asked.getFront();\n        System.out.println(days * 2 + \" days in two weeks\");\n    }\n}\n","hints":["The header is `public class Flashcard<F, B>`. The front is an F and the back a B: `private F front;` and `private B back;`, and `getFront()` returns an F, `getBack()` a B.","A flipped card has a B in front and an F at the back, so the return type of `flipped` is `Flashcard<B, F>`, and its body is `return new Flashcard<>(this.back, this.front);`. It makes a new card and leaves this one as it was."],"tests":[{"name":"Test 1","stdin":"","call":"Flashcard<String, String> word = new Flashcard<>(\"perro\", \"dog\");\nSystem.out.println(word);\nSystem.out.println(word.flipped());\nFlashcard<String, Integer> fact = new Flashcard<>(\"Days in a week\", 7);\nFlashcard<Integer, String> asked = fact.flipped();\nSystem.out.println(asked);\nint days = asked.getFront();\nSystem.out.println(days * 2 + \" days in two weeks\");\n","expect":"perro / dog\ndog / perro\n7 / Days in a week\n14 days in two weeks","hidden":false},{"name":"Test 2","stdin":"","call":"Flashcard<String, Boolean> claim = new Flashcard<>(\"Bats are blind\", false);\nFlashcard<Boolean, String> back = claim.flipped();\nSystem.out.println(claim);\nSystem.out.println(claim.getFront().length() + \" \" + claim.getBack());\nSystem.out.println(back.getFront() || back.getBack().isEmpty());\nSystem.out.println(back.flipped());\nFlashcard<Double, Integer> numbers = new Flashcard<>(0.5, 2);\nSystem.out.println(numbers.getFront() * numbers.getBack() + \" \" + numbers.flipped());\n","expect":"Bats are blind / false\n14 false\nfalse\nBats are blind / false\n1.0 2 / 0.5","hidden":true}],"require":[],"forbid":[],"more":[{"task":"Two lifeguards share the lake with this step's Rotation and Duo: each day one sits in the tower and the other walks the shore. Look at where the rotation's turn is after two calls to `next()`. What does this program print?\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Rotation<String> guards = new Rotation<>();\n        guards.add(\"Abena\");\n        guards.add(\"Joaquin\");\n        Duo<String, String> today = new Duo<>(guards.next(), guards.next());\n        Duo<String, String> tomorrow = today.swapped();\n        System.out.println(today.getFirst() + \" takes the tower, \" + today.getSecond() + \" walks the shore\");\n        System.out.println(tomorrow);\n        guards.add(\"Leilani\");\n        System.out.println(guards.next() + \" \" + guards.next());\n    }\n}\n// ==== Duo.java ====\npublic class Duo<A, B> {\n    private A first;\n    private B second;\n\n    public Duo(A first, B second) {\n        this.first = first;\n        this.second = second;\n    }\n\n    public A getFirst() {\n        return this.first;\n    }\n\n    public B getSecond() {\n        return this.second;\n    }\n\n    public Duo<B, A> swapped() {\n        return new Duo<>(this.second, this.first);\n    }\n\n    @Override\n    public String toString() {\n        return \"(\" + this.first + \", \" + this.second + \")\";\n    }\n}\n// ==== Rotation.java ====\nimport java.util.ArrayList;\n\npublic class Rotation<T> {\n    private ArrayList<T> members;\n    private int turn;\n\n    public Rotation() {\n        this.members = new ArrayList<>();\n        this.turn = 0;\n    }\n\n    public void add(T member) {\n        this.members.add(member);\n    }\n\n    public T next() {\n        T member = this.members.get(this.turn);\n        this.turn++;\n        if (this.turn == this.members.size()) {\n            this.turn = 0;\n        }\n        return member;\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Rotation<String> guards = new Rotation<>();\n        guards.add(\"Abena\");\n        guards.add(\"Joaquin\");\n        Duo<String, String> today = new Duo<>(guards.next(), guards.next());\n        Duo<String, String> tomorrow = today.swapped();\n        System.out.println(today.getFirst() + \" takes the tower, \" + today.getSecond() + \" walks the shore\");\n        System.out.println(tomorrow);\n        guards.add(\"Leilani\");\n        System.out.println(guards.next() + \" \" + guards.next());\n    }\n}\n// ==== Duo.java ====\npublic class Duo<A, B> {\n    private A first;\n    private B second;\n\n    public Duo(A first, B second) {\n        this.first = first;\n        this.second = second;\n    }\n\n    public A getFirst() {\n        return this.first;\n    }\n\n    public B getSecond() {\n        return this.second;\n    }\n\n    public Duo<B, A> swapped() {\n        return new Duo<>(this.second, this.first);\n    }\n\n    @Override\n    public String toString() {\n        return \"(\" + this.first + \", \" + this.second + \")\";\n    }\n}\n// ==== Rotation.java ====\nimport java.util.ArrayList;\n\npublic class Rotation<T> {\n    private ArrayList<T> members;\n    private int turn;\n\n    public Rotation() {\n        this.members = new ArrayList<>();\n        this.turn = 0;\n    }\n\n    public void add(T member) {\n        this.members.add(member);\n    }\n\n    public T next() {\n        T member = this.members.get(this.turn);\n        this.turn++;\n        if (this.turn == this.members.size()) {\n            this.turn = 0;\n        }\n        return member;\n    }\n}\n","hints":["The two `next()` calls give Abena and then Joaquin, and `swapped()` makes a new Duo the other way around. `today` itself doesn't change.","After Joaquin, the turn reached the size of the list, 2, so it went back to 0. Adding Leilani doesn't move the turn: the next two are Abena and Joaquin again."],"tests":[{"name":"Output","stdin":"","expect":"Abena takes the tower, Joaquin walks the shore\n(Joaquin, Abena)\nAbena Joaquin","hidden":false}],"require":[],"forbid":[],"lines":["Abena takes the tower, Joaquin walks the shore","(Joaquin, Abena)","Abena Joaquin"]},{"task":"At the finish line of a race, the first three get a place on the podium, and everyone else who finishes is only counted. In `Podium.java`, write the class `Podium<T>`, which keeps the first three in an `ArrayList<T>` (a `List<T>` variable that holds an ArrayList is fine too), with:\n\n- a constructor `Podium()`, which starts with nobody\n- `finish(T competitor)`, which records the next one to finish. Only the first three get a place.\n- `getPlace(int place)`, which returns the competitor in place 1, 2 or 3, or `null` if nobody has that place yet\n- `finishers()`, which returns how many have finished in all, on the podium or not\n\nA runner can be given by name, a `Podium<String>`, or by the number on their bib, a `Podium<Integer>`. The check runs:\n\n```java\nPodium<String> sprint = new Podium<>();\nsprint.finish(\"Mo\");\nsprint.finish(\"Lin\");\nsprint.finish(\"Ada\");\nsprint.finish(\"Kai\");\nSystem.out.println(sprint.getPlace(1) + \", \" + sprint.getPlace(2) + \", \" + sprint.getPlace(3));\nSystem.out.println(sprint.finishers() + \" finished\");\nPodium<Integer> marathon = new Podium<>();\nmarathon.finish(204);\nint winner = marathon.getPlace(1);\nSystem.out.println(\"Bib \" + winner + \" wins\");\n```\n\nand expects:\n\n```\nMo, Lin, Ada\n4 finished\nBib 204 wins\n```\n","kind":"code","seed":"// ==== Podium.java ====\nimport java.util.ArrayList;\n\npublic class Podium {\n\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Podium<String> sprint = new Podium<>();\n        sprint.finish(\"Mo\");\n        sprint.finish(\"Lin\");\n        sprint.finish(\"Ada\");\n        sprint.finish(\"Kai\");\n        System.out.println(sprint.getPlace(1) + \", \" + sprint.getPlace(2) + \", \" + sprint.getPlace(3));\n        System.out.println(sprint.finishers() + \" finished\");\n        Podium<Integer> marathon = new Podium<>();\n        marathon.finish(204);\n        int winner = marathon.getPlace(1);\n        System.out.println(\"Bib \" + winner + \" wins\");\n    }\n}\n","solution":"// ==== Podium.java ====\nimport java.util.ArrayList;\n\npublic class Podium<T> {\n    private ArrayList<T> places;\n    private int finishers;\n\n    public Podium() {\n        this.places = new ArrayList<>();\n        this.finishers = 0;\n    }\n\n    public void finish(T competitor) {\n        if (this.places.size() < 3) {\n            this.places.add(competitor);\n        }\n        this.finishers++;\n    }\n\n    public T getPlace(int place) {\n        if (place > this.places.size()) {\n            return null;\n        }\n        return this.places.get(place - 1);\n    }\n\n    public int finishers() {\n        return this.finishers;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Podium<String> sprint = new Podium<>();\n        sprint.finish(\"Mo\");\n        sprint.finish(\"Lin\");\n        sprint.finish(\"Ada\");\n        sprint.finish(\"Kai\");\n        System.out.println(sprint.getPlace(1) + \", \" + sprint.getPlace(2) + \", \" + sprint.getPlace(3));\n        System.out.println(sprint.finishers() + \" finished\");\n        Podium<Integer> marathon = new Podium<>();\n        marathon.finish(204);\n        int winner = marathon.getPlace(1);\n        System.out.println(\"Bib \" + winner + \" wins\");\n    }\n}\n","hints":["The header is `public class Podium<T>`, with `private ArrayList<T> places;` and an int that counts the finishers. The constructor makes the list with `new ArrayList<>()`.","`finish` adds the competitor only while the list has fewer than 3, and counts every finisher. Place 1 is at index 0, so `getPlace` returns `this.places.get(place - 1)`, or `null` when the place is past the end of the list."],"tests":[{"name":"Test 1","stdin":"","call":"Podium<String> sprint = new Podium<>();\nsprint.finish(\"Mo\");\nsprint.finish(\"Lin\");\nsprint.finish(\"Ada\");\nsprint.finish(\"Kai\");\nSystem.out.println(sprint.getPlace(1) + \", \" + sprint.getPlace(2) + \", \" + sprint.getPlace(3));\nSystem.out.println(sprint.finishers() + \" finished\");\nPodium<Integer> marathon = new Podium<>();\nmarathon.finish(204);\nint winner = marathon.getPlace(1);\nSystem.out.println(\"Bib \" + winner + \" wins\");\n","expect":"Mo, Lin, Ada\n4 finished\nBib 204 wins","hidden":false},{"name":"Test 2","stdin":"","call":"Podium<String> swim = new Podium<>();\nSystem.out.println(swim.finishers() + \" \" + swim.getPlace(1));\nswim.finish(\"Rosa\");\nswim.finish(\"Jun\");\nSystem.out.println(swim.getPlace(2) + \" \" + swim.getPlace(3) + \" \" + swim.finishers());\nfor (int i = 0; i < 6; i++) {\n    swim.finish(\"Late \" + i);\n}\nSystem.out.println(swim.getPlace(1) + \" \" + swim.getPlace(2) + \" \" + swim.getPlace(3) + \" \" + swim.finishers());\nPodium<Integer> bikes = new Podium<>();\nbikes.finish(31);\nbikes.finish(8);\nSystem.out.println(bikes.getPlace(1) + bikes.getPlace(2));\n","expect":"0 null\nJun null 2\nRosa Jun Late 0 8\n39","hidden":true}],"require":[{"pattern":"\\b(?:Array)?List\\s*<\\s*\\w+\\s*>","message":"Keep the podium's competitors in an `ArrayList<T>`, or in a `List<T>` that holds one."}],"forbid":[]}]}