{"id":"lists-of-objects-adding","slug":"a-list-of-objects","title":"A list of objects","text":"The lists in part 3 held Strings and Integers. The type in the angle brackets can be any class, including the ones you write yourself. Here's a `Pet` class, with a name, an age, two getters and a `toString`, and a list of pets:\n\n```java\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Pet> pets = new ArrayList<>();\n        pets.add(new Pet(\"Rex\", 4));\n        pets.add(new Pet(\"Misty\", 2));\n        Pet kiwi = new Pet(\"Kiwi\", 11);\n        pets.add(kiwi);\n\n        System.out.println(pets.size() + \" pets\");\n        for (Pet pet : pets) {\n            System.out.println(pet);\n        }\n        System.out.println(\"The first one is \" + pets.get(0).getName());\n    }\n}\n// ==== Pet.java ====\npublic class Pet {\n    private String name;\n    private int age;\n\n    public Pet(String name, int age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getAge() {\n        return this.age;\n    }\n\n    public String toString() {\n        return this.name + \", \" + this.age + \" years old\";\n    }\n}\n```\n\n```output\n3 pets\nRex, 4 years old\nMisty, 2 years old\nKiwi, 11 years old\nThe first one is Rex\n```\n\n- `ArrayList<Pet> pets = new ArrayList<>();` creates a list for `Pet` objects. Like every new list, it starts empty.\n- `pets.add(new Pet(\"Rex\", 4));` creates a pet and adds it in one go. The object needs no variable of its own: the list refers to it. Adding a pet that has a variable, like `kiwi`, works the same way.\n- In the for-each loop, `pet` is a `Pet`: in each round, the next object in the list. `System.out.println(pet)` prints what the object's `toString` returns.\n- `pets.get(0)` is a `Pet` too, so you can call its methods straight away: `pets.get(0).getName()`.\n\n`size()`, `get(index)` and `remove(index)` work just as they did with Strings. The methods that look for a value, such as `contains` and `indexOf`, are different: `pets.contains(new Pet(\"Rex\", 4))` is `false`, because the new pet is another object than the Rex in the list, even though its name and age are the same. (A later module shows how a class can change that.) To find a pet by its name or age, go through the list and ask each pet with a getter, as step 5 does.\n\nThe list takes only pets: `pets.add(\"Rex\")` doesn't compile, because a String isn't a `Pet`.\n\nPrinting an object whose class has no `toString` shows only the class name, an `@` and a code that can change from run to run. That's why the classes in this module have a `toString`.\n","task":"The `Camper` class is ready, in its own tab. In `main`, create a list `campers` and add three campers: Ines in tent 2, Tom in tent 5 and Mia in tent 2. Then print the number of campers with `size()`, followed by ` campers`, and every camper with a for-each loop. The program prints:\n\n```\n3 campers\nInes (tent 2)\nTom (tent 5)\nMia (tent 2)\n```\n","kind":"code","seed":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n\n    }\n}\n\n// ==== Camper.java ====\npublic class Camper {\n    private String name;\n    private int tent;\n\n    public Camper(String name, int tent) {\n        this.name = name;\n        this.tent = tent;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getTent() {\n        return this.tent;\n    }\n\n    public String toString() {\n        return this.name + \" (tent \" + this.tent + \")\";\n    }\n}\n","solution":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Camper> campers = new ArrayList<>();\n        campers.add(new Camper(\"Ines\", 2));\n        campers.add(new Camper(\"Tom\", 5));\n        campers.add(new Camper(\"Mia\", 2));\n\n        System.out.println(campers.size() + \" campers\");\n        for (Camper camper : campers) {\n            System.out.println(camper);\n        }\n    }\n}\n\n// ==== Camper.java ====\npublic class Camper {\n    private String name;\n    private int tent;\n\n    public Camper(String name, int tent) {\n        this.name = name;\n        this.tent = tent;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getTent() {\n        return this.tent;\n    }\n\n    public String toString() {\n        return this.name + \" (tent \" + this.tent + \")\";\n    }\n}\n","hints":["Create the list with `ArrayList<Camper> campers = new ArrayList<>();`, then add each camper with `campers.add(new Camper(\"Ines\", 2));`.","Print `campers.size() + \" campers\"` first. Then `for (Camper camper : campers) { System.out.println(camper); }` prints each camper with its `toString`."],"tests":[{"name":"The program","stdin":"","expect":"3 campers\nInes (tent 2)\nTom (tent 5)\nMia (tent 2)","hidden":false}],"require":[{"pattern":"ArrayList\\s*<\\s*Camper\\s*>","message":"Create the list as an `ArrayList<Camper>`."},{"pattern":"new\\s+Camper\\s*\\(","min":3,"message":"Create each of the three campers with `new Camper(...)`."},{"pattern":"\\.size\\s*\\(\\s*\\)","message":"Print the number of campers with `campers.size()`."},{"pattern":"for\\s*\\(\\s*Camper\\s+\\w+\\s*:","message":"Print the campers with a for-each loop: `for (Camper camper : campers)`."}],"forbid":[],"more":[{"task":"`Main.java` makes a list of hikes and prints it, but `Hike` has no `toString` yet, so each line shows only the class name, an `@` and a code. Add a `toString` method to `Hike` that returns the name, a colon and a space, and then the length, followed by ` km`. The program then prints:\n\n```\nLake loop: 12 km\nRidge path: 7 km\nOld mill: 4 km\n```\n","kind":"code","seed":"// ==== Hike.java ====\npublic class Hike {\n    private String name;\n    private int km;\n\n    public Hike(String name, int km) {\n        this.name = name;\n        this.km = km;\n    }\n\n    // Write the toString method here.\n}\n\n// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Hike> hikes = new ArrayList<>();\n        hikes.add(new Hike(\"Lake loop\", 12));\n        hikes.add(new Hike(\"Ridge path\", 7));\n        hikes.add(new Hike(\"Old mill\", 4));\n\n        for (Hike hike : hikes) {\n            System.out.println(hike);\n        }\n    }\n}\n","solution":"// ==== Hike.java ====\npublic class Hike {\n    private String name;\n    private int km;\n\n    public Hike(String name, int km) {\n        this.name = name;\n        this.km = km;\n    }\n\n    public String toString() {\n        return this.name + \": \" + this.km + \" km\";\n    }\n}\n\n// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Hike> hikes = new ArrayList<>();\n        hikes.add(new Hike(\"Lake loop\", 12));\n        hikes.add(new Hike(\"Ridge path\", 7));\n        hikes.add(new Hike(\"Old mill\", 4));\n\n        for (Hike hike : hikes) {\n            System.out.println(hike);\n        }\n    }\n}\n","hints":["The method goes inside the class, after the constructor: `public String toString() { ... }`.","It returns the text, it doesn't print it: `return this.name + \": \" + this.km + \" km\";`"],"tests":[{"name":"The program","stdin":"","expect":"Lake loop: 12 km\nRidge path: 7 km\nOld mill: 4 km","hidden":false},{"name":"System.out.println(new Hike(\"Coast trail\", 21));","stdin":"","call":"System.out.println(new Hike(\"Coast trail\", 21));\n","expect":"Coast trail: 21 km","hidden":true},{"name":"Test 3","stdin":"","call":"Hike hike = new Hike(\"Hill\", 3);\nSystem.out.println(hike + \"!\");\n","expect":"Hill: 3 km!","hidden":true}],"require":[{"pattern":"public\\s+String\\s+toString\\s*\\(\\s*\\)","message":"Write the method as `public String toString()`."}],"forbid":[]},{"task":"What does this program print? `Pet` is the class from the lesson.\n","kind":"predict","seed":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Pet> pets = new ArrayList<>();\n        pets.add(new Pet(\"Rex\", 4));\n        pets.add(new Pet(\"Misty\", 2));\n        pets.add(new Pet(\"Kiwi\", 11));\n        System.out.println(pets.size());\n        System.out.println(pets.get(1).getName());\n        pets.remove(0);\n        System.out.println(pets.get(0));\n        System.out.println(pets.size());\n    }\n}\n\n// ==== Pet.java ====\npublic class Pet {\n    private String name;\n    private int age;\n\n    public Pet(String name, int age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getAge() {\n        return this.age;\n    }\n\n    public String toString() {\n        return this.name + \", \" + this.age + \" years old\";\n    }\n}\n","solution":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Pet> pets = new ArrayList<>();\n        pets.add(new Pet(\"Rex\", 4));\n        pets.add(new Pet(\"Misty\", 2));\n        pets.add(new Pet(\"Kiwi\", 11));\n        System.out.println(pets.size());\n        System.out.println(pets.get(1).getName());\n        pets.remove(0);\n        System.out.println(pets.get(0));\n        System.out.println(pets.size());\n    }\n}\n\n// ==== Pet.java ====\npublic class Pet {\n    private String name;\n    private int age;\n\n    public Pet(String name, int age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getAge() {\n        return this.age;\n    }\n\n    public String toString() {\n        return this.name + \", \" + this.age + \" years old\";\n    }\n}\n","hints":["`get(1)` is the second pet, and `getName()` gives only its name.","`remove(0)` takes Rex out, so Misty moves to index 0. Printing a whole pet prints what its `toString` returns."],"tests":[{"name":"Output","stdin":"","expect":"3\nMisty\nMisty, 2 years old\n2","hidden":false}],"require":[],"forbid":[],"lines":["3","Misty","Misty, 2 years old","2"]}]}