{"id":"objects-with-lists-going-through","slug":"going-through-the-list","title":"Methods that go through the list","text":"An object's methods can do anything with its list that code in `main` could: go through it with a loop, look for a value, count things. Here the recipe gets two more methods:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Recipe soup = new Recipe(\"Tomato soup\");\n        soup.addIngredient(\"tomatoes\");\n        soup.addIngredient(\"onion\");\n        soup.addIngredient(\"salt\");\n        soup.printIngredients();\n        System.out.println(soup.needs(\"onion\"));\n        System.out.println(soup.needs(\"milk\"));\n    }\n}\n// ==== Recipe.java ====\nimport java.util.ArrayList;\n\npublic class Recipe {\n    private String name;\n    private ArrayList<String> ingredients;\n\n    public Recipe(String name) {\n        this.name = name;\n        this.ingredients = new ArrayList<>();\n    }\n\n    public void addIngredient(String ingredient) {\n        this.ingredients.add(ingredient);\n    }\n\n    public void printIngredients() {\n        System.out.println(this.name + \":\");\n        for (String ingredient : this.ingredients) {\n            System.out.println(\"- \" + ingredient);\n        }\n    }\n\n    public boolean needs(String ingredient) {\n        return this.ingredients.contains(ingredient);\n    }\n}\n```\n\n```output\nTomato soup:\n- tomatoes\n- onion\n- salt\ntrue\nfalse\n```\n\n- `for (String ingredient : this.ingredients)` goes through the recipe's own list. It's the loop you know from `main`; only the list is now `this.ingredients`.\n- `printIngredients` is `void`: it prints, and returns nothing. It prints the recipe's name first, because a method can use all of its object's instance variables together.\n- `needs` passes the question on to the list. `contains` goes through the list for you and compares with `equals` (module 23), so it finds `\"onion\"` however the String was made.\n\nA method with its own name, such as `needs`, also says what the question means for a recipe. `soup.needs(\"onion\")` reads better than a list call in `main`, and `main` doesn't need to know that the ingredients are kept in a list at all.\n\n### A loop of your own\n\n`contains` answers one question: is this exact value on the list? For any other question, write the loop yourself. This method tells whether any ingredient has a word in it, so that `needsAny(\"cheese\")` is true for a recipe with `goat cheese`:\n\n```java\npublic boolean needsAny(String word) {\n    for (String ingredient : this.ingredients) {\n        if (ingredient.contains(word)) {\n            return true;\n        }\n    }\n    return false;\n}\n```\n\nHere `ingredient.contains(word)` is the String method from module 16: it looks for the word inside one ingredient's name. For a pie with `goat cheese` and `spinach`, `needsAny(\"cheese\")` is `true`, while `needs(\"cheese\")` is `false`, since no ingredient is exactly `cheese`. The `return true` in the loop ends the method as soon as one ingredient matches, and `return false` after the loop runs only when none did (module 11).\n","task":"A garden keeps a list of the plants that grow in it. `Garden.java` has the list and the method `plant(String name)`. Write two more methods in it:\n\n- `print()` prints each plant on a line of its own, starting with `* `.\n- `grows(String name)` returns `true` when that plant is in the garden.\n\nThe check runs:\n\n```java\nGarden garden = new Garden();\ngarden.plant(\"rose\");\ngarden.plant(\"mint\");\ngarden.plant(\"fern\");\ngarden.print();\nSystem.out.println(garden.grows(\"mint\"));\nSystem.out.println(garden.grows(\"oak\"));\n```\n\nand expects:\n\n```\n* rose\n* mint\n* fern\ntrue\nfalse\n```\n","kind":"code","seed":"// ==== Garden.java ====\nimport java.util.ArrayList;\n\npublic class Garden {\n    private ArrayList<String> plants;\n\n    public Garden() {\n        this.plants = new ArrayList<>();\n    }\n\n    public void plant(String name) {\n        this.plants.add(name);\n    }\n\n    // Write the methods print and grows here.\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Garden garden = new Garden();\n        garden.plant(\"rose\");\n        garden.plant(\"mint\");\n        garden.plant(\"fern\");\n        garden.print();\n        System.out.println(garden.grows(\"mint\"));\n        System.out.println(garden.grows(\"oak\"));\n    }\n}\n","solution":"// ==== Garden.java ====\nimport java.util.ArrayList;\n\npublic class Garden {\n    private ArrayList<String> plants;\n\n    public Garden() {\n        this.plants = new ArrayList<>();\n    }\n\n    public void plant(String name) {\n        this.plants.add(name);\n    }\n\n    public void print() {\n        for (String plant : this.plants) {\n            System.out.println(\"* \" + plant);\n        }\n    }\n\n    public boolean grows(String name) {\n        return this.plants.contains(name);\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Garden garden = new Garden();\n        garden.plant(\"rose\");\n        garden.plant(\"mint\");\n        garden.plant(\"fern\");\n        garden.print();\n        System.out.println(garden.grows(\"mint\"));\n        System.out.println(garden.grows(\"oak\"));\n    }\n}\n","hints":["`print` is a for-each loop over the garden's own list, `this.plants`. `grows` can pass its question on to one of the list's own methods.","`for (String plant : this.plants) { System.out.println(\"* \" + plant); }` prints the plants, and `return this.plants.contains(name);` answers `grows`."],"tests":[{"name":"Test 1","stdin":"","call":"Garden garden = new Garden();\ngarden.plant(\"rose\");\ngarden.plant(\"mint\");\ngarden.plant(\"fern\");\ngarden.print();\nSystem.out.println(garden.grows(\"mint\"));\nSystem.out.println(garden.grows(\"oak\"));\n","expect":"* rose\n* mint\n* fern\ntrue\nfalse","hidden":false},{"name":"Test 2","stdin":"","call":"Garden garden = new Garden();\ngarden.print();\nSystem.out.println(garden.grows(\"rose\"));\nString name = \"tu\";\ngarden.plant(name + \"lip\");\ngarden.plant(\"tulip\");\ngarden.print();\nSystem.out.println(garden.grows(\"tulip\") + \" \" + garden.grows(\"tul\"));\n","expect":"false\n* tulip\n* tulip\ntrue false","hidden":true},{"name":"Test 3","stdin":"","call":"Garden north = new Garden();\nGarden south = new Garden();\nnorth.plant(\"birch\");\nsouth.plant(\"palm\");\nsouth.plant(\"cactus\");\nsouth.print();\nSystem.out.println(north.grows(\"palm\") + \" \" + south.grows(\"palm\"));\n","expect":"* palm\n* cactus\nfalse true","hidden":true}],"require":[{"pattern":"\\bpublic\\s+void\\s+print\\s*\\(\\s*\\)","message":"Write the method as `public void print()`."},{"pattern":"\\bpublic\\s+boolean\\s+grows\\s*\\(\\s*String\\s+\\w+\\s*\\)","message":"Write the method as `public boolean grows(String name)`."}],"forbid":[],"more":[{"task":"What does this program print? Look at which `contains` each method uses: the list's, or the String's.\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Wardrobe wardrobe = new Wardrobe();\n        wardrobe.hang(\"red scarf\");\n        wardrobe.hang(\"blue coat\");\n        wardrobe.hang(\"red coat\");\n        wardrobe.hang(\"scarf\");\n        System.out.println(wardrobe.has(\"coat\"));\n        System.out.println(wardrobe.has(\"scarf\"));\n        System.out.println(wardrobe.count(\"coat\"));\n        System.out.println(wardrobe.count(\"red\"));\n    }\n}\n// ==== Wardrobe.java ====\nimport java.util.ArrayList;\n\npublic class Wardrobe {\n    private ArrayList<String> clothes;\n\n    public Wardrobe() {\n        this.clothes = new ArrayList<>();\n    }\n\n    public void hang(String item) {\n        this.clothes.add(item);\n    }\n\n    public boolean has(String item) {\n        return this.clothes.contains(item);\n    }\n\n    public int count(String word) {\n        int count = 0;\n        for (String item : this.clothes) {\n            if (item.contains(word)) {\n                count++;\n            }\n        }\n        return count;\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Wardrobe wardrobe = new Wardrobe();\n        wardrobe.hang(\"red scarf\");\n        wardrobe.hang(\"blue coat\");\n        wardrobe.hang(\"red coat\");\n        wardrobe.hang(\"scarf\");\n        System.out.println(wardrobe.has(\"coat\"));\n        System.out.println(wardrobe.has(\"scarf\"));\n        System.out.println(wardrobe.count(\"coat\"));\n        System.out.println(wardrobe.count(\"red\"));\n    }\n}\n// ==== Wardrobe.java ====\nimport java.util.ArrayList;\n\npublic class Wardrobe {\n    private ArrayList<String> clothes;\n\n    public Wardrobe() {\n        this.clothes = new ArrayList<>();\n    }\n\n    public void hang(String item) {\n        this.clothes.add(item);\n    }\n\n    public boolean has(String item) {\n        return this.clothes.contains(item);\n    }\n\n    public int count(String word) {\n        int count = 0;\n        for (String item : this.clothes) {\n            if (item.contains(word)) {\n                count++;\n            }\n        }\n        return count;\n    }\n}\n","hints":["`has` asks the list, and the list's `contains` looks for a value that equals the whole String. No item is exactly `coat`, but one is exactly `scarf`.","`count` uses the String's `contains`, which looks for the word inside each item: `blue coat` and `red coat` have `coat` in them, and `red scarf` and `red coat` have `red`."],"tests":[{"name":"Output","stdin":"","expect":"false\ntrue\n2\n2","hidden":false}],"require":[],"forbid":[],"lines":["false","true","2","2"]},{"task":"A guestbook keeps a name for every visit, so the same name can be in it many times. `Guestbook.java` has the list and the method `sign(String name)`. Write two more methods:\n\n- `visits(String name)` returns how many times the name is in the guestbook. `contains` can't count, so go through the list yourself, and compare the names with `equals`.\n- `printNames()` prints every name once, in the order of their first visits.\n\nThe check runs:\n\n```java\nGuestbook book = new Guestbook();\nbook.sign(\"Ada\");\nbook.sign(\"Leo\");\nbook.sign(\"Ada\");\nbook.sign(\"Mia\");\nbook.sign(\"Ada\");\nSystem.out.println(book.visits(\"Ada\") + \" \" + book.visits(\"Leo\") + \" \" + book.visits(\"Zed\"));\nbook.printNames();\n```\n\nand expects:\n\n```\n3 1 0\nAda\nLeo\nMia\n```\n","kind":"code","seed":"// ==== Guestbook.java ====\nimport java.util.ArrayList;\n\npublic class Guestbook {\n    private ArrayList<String> names;\n\n    public Guestbook() {\n        this.names = new ArrayList<>();\n    }\n\n    public void sign(String name) {\n        this.names.add(name);\n    }\n\n    // Write the methods visits and printNames here.\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Guestbook book = new Guestbook();\n        book.sign(\"Ada\");\n        book.sign(\"Leo\");\n        book.sign(\"Ada\");\n        book.sign(\"Mia\");\n        book.sign(\"Ada\");\n        System.out.println(book.visits(\"Ada\") + \" \" + book.visits(\"Leo\") + \" \" + book.visits(\"Zed\"));\n        book.printNames();\n    }\n}\n","solution":"// ==== Guestbook.java ====\nimport java.util.ArrayList;\n\npublic class Guestbook {\n    private ArrayList<String> names;\n\n    public Guestbook() {\n        this.names = new ArrayList<>();\n    }\n\n    public void sign(String name) {\n        this.names.add(name);\n    }\n\n    public int visits(String name) {\n        int count = 0;\n        for (String visitor : this.names) {\n            if (visitor.equals(name)) {\n                count++;\n            }\n        }\n        return count;\n    }\n\n    public void printNames() {\n        ArrayList<String> printed = new ArrayList<>();\n        for (String visitor : this.names) {\n            if (!printed.contains(visitor)) {\n                System.out.println(visitor);\n                printed.add(visitor);\n            }\n        }\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Guestbook book = new Guestbook();\n        book.sign(\"Ada\");\n        book.sign(\"Leo\");\n        book.sign(\"Ada\");\n        book.sign(\"Mia\");\n        book.sign(\"Ada\");\n        System.out.println(book.visits(\"Ada\") + \" \" + book.visits(\"Leo\") + \" \" + book.visits(\"Zed\"));\n        book.printNames();\n    }\n}\n","hints":["`visits` counts in a loop: start with `int count = 0;`, go through `this.names`, and add one when `visitor.equals(name)`. Return the count after the loop.","For `printNames`, keep a local list of the names already printed. For each name in the guestbook: if `printed` doesn't contain it yet, print it and add it to `printed`."],"tests":[{"name":"Test 1","stdin":"","call":"Guestbook book = new Guestbook();\nbook.sign(\"Ada\");\nbook.sign(\"Leo\");\nbook.sign(\"Ada\");\nbook.sign(\"Mia\");\nbook.sign(\"Ada\");\nSystem.out.println(book.visits(\"Ada\") + \" \" + book.visits(\"Leo\") + \" \" + book.visits(\"Zed\"));\nbook.printNames();\n","expect":"3 1 0\nAda\nLeo\nMia","hidden":false},{"name":"Test 2","stdin":"","call":"Guestbook book = new Guestbook();\nString first = \"Jo\";\nbook.sign(first + \"nas\");\nbook.sign(\"Jonas\");\nbook.sign(\"Kim\");\nSystem.out.println(book.visits(\"Jonas\") + \" \" + book.visits(\"jonas\"));\nbook.printNames();\n","expect":"2 0\nJonas\nKim","hidden":true},{"name":"Test 3","stdin":"","call":"Guestbook book = new Guestbook();\nSystem.out.println(book.visits(\"Ada\"));\nbook.printNames();\nbook.sign(\"Zoe\");\nbook.sign(\"Yan\");\nbook.sign(\"Yan\");\nbook.sign(\"Zoe\");\nbook.sign(\"Xia\");\nbook.printNames();\nSystem.out.println(book.visits(\"Yan\"));\n","expect":"0\nZoe\nYan\nXia\n2","hidden":true}],"require":[{"pattern":"\\bpublic\\s+int\\s+visits\\s*\\(\\s*String\\s+\\w+\\s*\\)","message":"Write the method as `public int visits(String name)`."},{"pattern":"\\.equals\\s*\\(","message":"In `visits`, compare the names with `equals`."}],"forbid":[]}]}