{"id":"lists-of-objects-searching","slug":"finding-in-the-list","title":"Finding in the list","text":"Module 13 found the largest number in a list: keep the largest one so far in a variable, and replace it whenever a larger one comes along. With objects, the variable holds a whole object. After the loop you have the largest value and also whose it is:\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        pets.add(new Pet(\"Kiwi\", 11));\n\n        System.out.println(\"Oldest: \" + findOldest(pets));\n        printPet(pets, \"Misty\");\n        printPet(pets, \"Bo\");\n    }\n\n    public static Pet findOldest(ArrayList<Pet> pets) {\n        Pet oldest = pets.get(0);\n        for (Pet pet : pets) {\n            if (pet.getAge() > oldest.getAge()) {\n                oldest = pet;\n            }\n        }\n        return oldest;\n    }\n\n    public static void printPet(ArrayList<Pet> pets, String name) {\n        for (Pet pet : pets) {\n            if (pet.getName().equals(name)) {\n                System.out.println(\"Found: \" + pet);\n                return;\n            }\n        }\n        System.out.println(\"No pet called \" + name);\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\nOldest: Kiwi, 11 years old\nFound: Misty, 2 years old\nNo pet called Bo\n```\n\n- `Pet oldest = pets.get(0);` starts from the first pet, which is always a real candidate. The loop compares every pet's age with the oldest one so far, and when a pet is older, it becomes the new `oldest`.\n- `findOldest` returns a `Pet`: a method can return an object, like any other value. The caller gets the whole pet, and can print it or call its getters.\n- With `>`, the first of two pets of the same age stays the oldest; with `>=`, the later one would win.\n- `get(0)` needs at least one pet in the list. When the list might be empty, check `pets.isEmpty()` first.\n\n### Finding one by name\n\n`printPet` goes through the list until a pet's name `equals` the name it's looking for (with `==`, Strings aren't compared reliably). The `return` ends the method as soon as the pet is found. Only when the loop gets through the whole list without finding it does the last line run.\n","task":"`Swimmer.java` is ready. Write a method `fastest(ArrayList<Swimmer> swimmers)` that returns the swimmer with the smallest time. When two swimmers share the best time, return the one that comes first in the list. The list always has at least one swimmer. The check runs `System.out.println(fastest(swimmers));` for the list in `main` and expects:\n\n```\nTom (64 s)\n```\n","kind":"code","seed":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Swimmer> swimmers = new ArrayList<>();\n        swimmers.add(new Swimmer(\"Ines\", 71));\n        swimmers.add(new Swimmer(\"Tom\", 64));\n        swimmers.add(new Swimmer(\"Mia\", 68));\n        System.out.println(fastest(swimmers));\n    }\n\n    // Write the fastest method here.\n}\n\n// ==== Swimmer.java ====\npublic class Swimmer {\n    private String name;\n    private int seconds;\n\n    public Swimmer(String name, int seconds) {\n        this.name = name;\n        this.seconds = seconds;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getSeconds() {\n        return this.seconds;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.seconds + \" s)\";\n    }\n}\n","solution":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Swimmer> swimmers = new ArrayList<>();\n        swimmers.add(new Swimmer(\"Ines\", 71));\n        swimmers.add(new Swimmer(\"Tom\", 64));\n        swimmers.add(new Swimmer(\"Mia\", 68));\n        System.out.println(fastest(swimmers));\n    }\n\n    public static Swimmer fastest(ArrayList<Swimmer> swimmers) {\n        Swimmer best = swimmers.get(0);\n        for (Swimmer swimmer : swimmers) {\n            if (swimmer.getSeconds() < best.getSeconds()) {\n                best = swimmer;\n            }\n        }\n        return best;\n    }\n}\n\n// ==== Swimmer.java ====\npublic class Swimmer {\n    private String name;\n    private int seconds;\n\n    public Swimmer(String name, int seconds) {\n        this.name = name;\n        this.seconds = seconds;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getSeconds() {\n        return this.seconds;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.seconds + \" s)\";\n    }\n}\n","hints":["The method returns a swimmer, so it starts `public static Swimmer fastest(ArrayList<Swimmer> swimmers) {`. Begin with `Swimmer best = swimmers.get(0);`.","Replace `best` when `swimmer.getSeconds() < best.getSeconds()`. With `<` and not `<=`, the first of two equal times stays. Return `best` after the loop."],"tests":[{"name":"The list in main","stdin":"","call":"ArrayList<Swimmer> swimmers = new ArrayList<>();\nswimmers.add(new Swimmer(\"Ines\", 71));\nswimmers.add(new Swimmer(\"Tom\", 64));\nswimmers.add(new Swimmer(\"Mia\", 68));\nSystem.out.println(fastest(swimmers));\n","expect":"Tom (64 s)","hidden":false},{"name":"The fastest comes first","stdin":"","call":"ArrayList<Swimmer> swimmers = new ArrayList<>();\nswimmers.add(new Swimmer(\"Ada\", 59));\nswimmers.add(new Swimmer(\"Ben\", 60));\nswimmers.add(new Swimmer(\"Cleo\", 75));\nSystem.out.println(fastest(swimmers));\n","expect":"Ada (59 s)","hidden":true},{"name":"The fastest comes last","stdin":"","call":"ArrayList<Swimmer> swimmers = new ArrayList<>();\nswimmers.add(new Swimmer(\"Ada\", 90));\nswimmers.add(new Swimmer(\"Ben\", 82));\nswimmers.add(new Swimmer(\"Cleo\", 77));\nSystem.out.println(fastest(swimmers).getName());\n","expect":"Cleo","hidden":true},{"name":"Two equal times","stdin":"","call":"ArrayList<Swimmer> swimmers = new ArrayList<>();\nswimmers.add(new Swimmer(\"Ada\", 70));\nswimmers.add(new Swimmer(\"Ben\", 66));\nswimmers.add(new Swimmer(\"Cleo\", 66));\nSystem.out.println(fastest(swimmers));\n","expect":"Ben (66 s)","hidden":true},{"name":"Only one swimmer","stdin":"","call":"ArrayList<Swimmer> swimmers = new ArrayList<>();\nswimmers.add(new Swimmer(\"Dev\", 101));\nSystem.out.println(fastest(swimmers));\n","expect":"Dev (101 s)","hidden":true}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Watch the two comparisons when two pets are the same age.\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\", 7));\n        pets.add(new Pet(\"Kiwi\", 7));\n        pets.add(new Pet(\"Bo\", 2));\n        pets.add(new Pet(\"Nala\", 2));\n\n        Pet oldest = pets.get(0);\n        Pet youngest = pets.get(0);\n        for (Pet pet : pets) {\n            if (pet.getAge() >= oldest.getAge()) {\n                oldest = pet;\n            }\n            if (pet.getAge() < youngest.getAge()) {\n                youngest = pet;\n            }\n        }\n        System.out.println(oldest.getName());\n        System.out.println(youngest.getName());\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\", 7));\n        pets.add(new Pet(\"Kiwi\", 7));\n        pets.add(new Pet(\"Bo\", 2));\n        pets.add(new Pet(\"Nala\", 2));\n\n        Pet oldest = pets.get(0);\n        Pet youngest = pets.get(0);\n        for (Pet pet : pets) {\n            if (pet.getAge() >= oldest.getAge()) {\n                oldest = pet;\n            }\n            if (pet.getAge() < youngest.getAge()) {\n                youngest = pet;\n            }\n        }\n        System.out.println(oldest.getName());\n        System.out.println(youngest.getName());\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":["`>=` also replaces `oldest` with a pet of the same age, so of Misty and Kiwi (both 7), the later one wins.","`<` replaces `youngest` only with a pet that's really younger. Bo (2) replaces Rex, but Nala (also 2) doesn't replace Bo."],"tests":[{"name":"Output","stdin":"","expect":"Kiwi\nBo","hidden":false}],"require":[],"forbid":[],"lines":["Kiwi","Bo"]},{"task":"A program to end the module, with a class of your own. First write `Crop`: a crop has a name and a weight in kilos, kept in private object variables, and it prints like `potatoes (42 kg)`. Then write `main`. Read crops, a name and then the kilos, until the name is an empty line. Then print:\n\n- `10 kg or more:` and then every crop of at least 10 kilos, one per line;\n- `Total: ` with the kilos of all the crops added up, and ` kg`;\n- `Best: ` and the heaviest crop (the first of them, if two weigh the same).\n\nIf no crops were entered, print only `No crops.` For the input `potatoes`, `42`, `beans`, `3`, `carrots`, `12` and an empty line, the program prints:\n\n```\n10 kg or more:\npotatoes (42 kg)\ncarrots (12 kg)\nTotal: 57 kg\nBest: potatoes (42 kg)\n```\n","kind":"code","seed":"// ==== Crop.java ====\npublic class Crop {\n\n}\n\n// ==== Main.java ====\nimport java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayList<Crop> crops = new ArrayList<>();\n\n    }\n}\n","solution":"// ==== Crop.java ====\npublic class Crop {\n    private String name;\n    private int kilos;\n\n    public Crop(String name, int kilos) {\n        this.name = name;\n        this.kilos = kilos;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getKilos() {\n        return this.kilos;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.kilos + \" kg)\";\n    }\n}\n\n// ==== Main.java ====\nimport java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayList<Crop> crops = new ArrayList<>();\n\n        while (true) {\n            String name = scanner.nextLine();\n            if (name.isEmpty()) {\n                break;\n            }\n            int kilos = Integer.valueOf(scanner.nextLine());\n            crops.add(new Crop(name, kilos));\n        }\n\n        if (crops.isEmpty()) {\n            System.out.println(\"No crops.\");\n            return;\n        }\n\n        System.out.println(\"10 kg or more:\");\n        int total = 0;\n        Crop best = crops.get(0);\n        for (Crop crop : crops) {\n            if (crop.getKilos() >= 10) {\n                System.out.println(crop);\n            }\n            total += crop.getKilos();\n            if (crop.getKilos() > best.getKilos()) {\n                best = crop;\n            }\n        }\n        System.out.println(\"Total: \" + total + \" kg\");\n        System.out.println(\"Best: \" + best);\n    }\n}\n","hints":["`Crop` needs `private String name;` and `private int kilos;`, a constructor `public Crop(String name, int kilos)`, a getter `getKilos()` and `toString()`.","In `main`: the reading loop, then `if (crops.isEmpty())` for `No crops.`. One for-each loop can do the rest: print the crops of 10 kilos or more, add up the kilos, and keep the heaviest crop so far, starting from `crops.get(0)`."],"tests":[{"name":"Test 1","stdin":"potatoes\n42\nbeans\n3\ncarrots\n12\n\n","expect":"10 kg or more:\npotatoes (42 kg)\ncarrots (12 kg)\nTotal: 57 kg\nBest: potatoes (42 kg)","hidden":false},{"name":"Test 2","stdin":"\n","expect":"No crops.","hidden":true},{"name":"Test 3","stdin":"herbs\n2\nbeans\n3\n\n","expect":"10 kg or more:\nTotal: 5 kg\nBest: beans (3 kg)","hidden":true},{"name":"Test 4","stdin":"leeks\n15\nkale\n15\nonions\n9\n\n","expect":"10 kg or more:\nleeks (15 kg)\nkale (15 kg)\nTotal: 39 kg\nBest: leeks (15 kg)","hidden":true},{"name":"Test 5","stdin":"peas\n10\nsquash\n31\n\n","expect":"10 kg or more:\npeas (10 kg)\nsquash (31 kg)\nTotal: 41 kg\nBest: squash (31 kg)","hidden":true}],"require":[{"pattern":"private\\s+(String|int)\\s+\\w+\\s*;","min":2,"message":"Keep the name and the kilos in private object variables, such as `private int kilos;`."},{"pattern":"new\\s+Crop\\s*\\(","message":"Create a `Crop` object for each crop that's read."}],"forbid":[]}]}