{"id":"lists-of-objects-filtering","slug":"choosing-from-the-list","title":"Choosing from the list","text":"A loop over the list doesn't have to print every object. An `if` inside it picks the ones to print, and the getters give the values to test:\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(\"At least 3 years old:\");\n        printAtLeast(pets, 3);\n        System.out.println(\"At least 10 years old:\");\n        printAtLeast(pets, 10);\n    }\n\n    public static void printAtLeast(ArrayList<Pet> pets, int minAge) {\n        for (Pet pet : pets) {\n            if (pet.getAge() >= minAge) {\n                System.out.println(pet);\n            }\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```\n\n```output\nAt least 3 years old:\nRex, 4 years old\nKiwi, 11 years old\nAt least 10 years old:\nKiwi, 11 years old\n```\n\n- `pet.getAge()` is the age of this round's pet. The condition can use any getter, and anything that works on the value it returns: `pet.getName().startsWith(\"K\")`, or `pet.getName().equals(name)`.\n- The getter is needed because `age` is private. `pet.age` in `Main` doesn't compile: javac says `age has private access in Pet`.\n- The list can be a method's parameter, as in module 14. The method then works for any list of pets and any age.\n\n### The limit from the user\n\nOften the list is read first, and then the user says what to look for. The loop that reads the list stops at the empty line, so the next `nextLine()` reads the line after it:\n\n```java\n// ... the loop that reads the pets, until an empty line\nint minAge = Integer.valueOf(scanner.nextLine());\nprintAtLeast(pets, minAge);\n```\n\n### When nothing matches\n\nTo say so when no object matched, count the matches while printing, and check the count after the loop:\n\n```java\nint count = 0;\nfor (Pet pet : pets) {\n    if (pet.getAge() >= minAge) {\n        System.out.println(pet);\n        count++;\n    }\n}\nif (count == 0) {\n    System.out.println(\"No pets that old\");\n}\n```\n","task":"What does this program print? Check the condition for each pet in turn.\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        pets.add(new Pet(\"Bo\", 3));\n\n        int count = 0;\n        for (Pet pet : pets) {\n            if (pet.getAge() > 3 || pet.getName().startsWith(\"M\")) {\n                System.out.println(pet.getName());\n                count++;\n            }\n        }\n        System.out.println(count + \" of \" + 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        pets.add(new Pet(\"Bo\", 3));\n\n        int count = 0;\n        for (Pet pet : pets) {\n            if (pet.getAge() > 3 || pet.getName().startsWith(\"M\")) {\n                System.out.println(pet.getName());\n                count++;\n            }\n        }\n        System.out.println(count + \" of \" + 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":["With `||`, a pet is printed when it's older than 3, or when its name starts with M. Misty is only 2, but her name starts with M.","Bo is 3, which isn't more than 3, and his name doesn't start with M. So three pets are printed, and the count is 3 of the 4."],"tests":[{"name":"Output","stdin":"","expect":"Rex\nMisty\nKiwi\n3 of 4","hidden":false}],"require":[],"forbid":[],"lines":["Rex","Misty","Kiwi","3 of 4"],"more":[{"task":"A yearly bird count. Each line of the input holds a species, last year's count and this year's count, separated by commas, like `robin,15,12`. The input ends with an empty line. `BirdCount.java` is ready. Read the lines into the list `counts`. Then print every species that was seen less this year than last year, with how many fewer birds, like `robin: 3 fewer`, in the order they were read. Last, print how many of the species went down, like `2 of 4 species went down`. For the input `robin,15,12`, `heron,4,6`, `sparrow,40,31`, `owl,2,2` and an empty line, the program prints:\n\n```\nrobin: 3 fewer\nsparrow: 9 fewer\n2 of 4 species went down\n```\n","kind":"code","seed":"// ==== 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<BirdCount> counts = new ArrayList<>();\n\n    }\n}\n\n// ==== BirdCount.java ====\npublic class BirdCount {\n    private String species;\n    private int lastYear;\n    private int thisYear;\n\n    public BirdCount(String species, int lastYear, int thisYear) {\n        this.species = species;\n        this.lastYear = lastYear;\n        this.thisYear = thisYear;\n    }\n\n    public String getSpecies() {\n        return this.species;\n    }\n\n    public int getLastYear() {\n        return this.lastYear;\n    }\n\n    public int getThisYear() {\n        return this.thisYear;\n    }\n}\n","solution":"// ==== 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<BirdCount> counts = new ArrayList<>();\n\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.isEmpty()) {\n                break;\n            }\n            String[] parts = line.split(\",\");\n            counts.add(new BirdCount(parts[0], Integer.valueOf(parts[1]), Integer.valueOf(parts[2])));\n        }\n\n        int down = 0;\n        for (BirdCount count : counts) {\n            if (count.getThisYear() < count.getLastYear()) {\n                int fewer = count.getLastYear() - count.getThisYear();\n                System.out.println(count.getSpecies() + \": \" + fewer + \" fewer\");\n                down++;\n            }\n        }\n        System.out.println(down + \" of \" + counts.size() + \" species went down\");\n    }\n}\n\n// ==== BirdCount.java ====\npublic class BirdCount {\n    private String species;\n    private int lastYear;\n    private int thisYear;\n\n    public BirdCount(String species, int lastYear, int thisYear) {\n        this.species = species;\n        this.lastYear = lastYear;\n        this.thisYear = thisYear;\n    }\n\n    public String getSpecies() {\n        return this.species;\n    }\n\n    public int getLastYear() {\n        return this.lastYear;\n    }\n\n    public int getThisYear() {\n        return this.thisYear;\n    }\n}\n","hints":["Read the lines as in the last step: `split(\",\")` gives the species in `parts[0]` and the two counts, as text, in `parts[1]` and `parts[2]`.","The condition compares two getters of the same object: `count.getThisYear() < count.getLastYear()`. The difference is `count.getLastYear() - count.getThisYear()`. Count the species you print, and print the last line after the loop."],"tests":[{"name":"Test 1","stdin":"robin,15,12\nheron,4,6\nsparrow,40,31\nowl,2,2\n\n","expect":"robin: 3 fewer\nsparrow: 9 fewer\n2 of 4 species went down","hidden":false},{"name":"Test 2","stdin":"crow,7,9\nwren,3,3\n\n","expect":"0 of 2 species went down","hidden":true},{"name":"Test 3","stdin":"gull,50,8\n\n","expect":"gull: 42 fewer\n1 of 1 species went down","hidden":true},{"name":"Test 4","stdin":"tit,20,19\nswift,11,12\njay,6,1\nkite,2,5\nlark,9,4\n\n","expect":"tit: 1 fewer\njay: 5 fewer\nlark: 5 fewer\n3 of 5 species went down","hidden":true}],"require":[{"pattern":"new\\s+BirdCount\\s*\\(","message":"Create a `BirdCount` object for each line."}],"forbid":[]},{"task":"Write a method `printFrom(ArrayList<Friend> friends, String city)` that prints the name of every friend who lives in `city`, one per line, and then how many there were, like `2 in Lisbon`. `Friend.java` is ready. The check calls the method with the list in `main` (Ines and Mia in Lisbon, Tom in Leeds) and the city `Lisbon`, and expects:\n\n```\nInes\nMia\n2 in Lisbon\n```\n","kind":"code","seed":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Friend> friends = new ArrayList<>();\n        friends.add(new Friend(\"Ines\", \"Lisbon\"));\n        friends.add(new Friend(\"Tom\", \"Leeds\"));\n        friends.add(new Friend(\"Mia\", \"Lisbon\"));\n        printFrom(friends, \"Lisbon\");\n    }\n\n    // Write the printFrom method here.\n}\n\n// ==== Friend.java ====\npublic class Friend {\n    private String name;\n    private String city;\n\n    public Friend(String name, String city) {\n        this.name = name;\n        this.city = city;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String getCity() {\n        return this.city;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.city + \")\";\n    }\n}\n","solution":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Friend> friends = new ArrayList<>();\n        friends.add(new Friend(\"Ines\", \"Lisbon\"));\n        friends.add(new Friend(\"Tom\", \"Leeds\"));\n        friends.add(new Friend(\"Mia\", \"Lisbon\"));\n        printFrom(friends, \"Lisbon\");\n    }\n\n    public static void printFrom(ArrayList<Friend> friends, String city) {\n        int count = 0;\n        for (Friend friend : friends) {\n            if (friend.getCity().equals(city)) {\n                System.out.println(friend.getName());\n                count++;\n            }\n        }\n        System.out.println(count + \" in \" + city);\n    }\n}\n\n// ==== Friend.java ====\npublic class Friend {\n    private String name;\n    private String city;\n\n    public Friend(String name, String city) {\n        this.name = name;\n        this.city = city;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String getCity() {\n        return this.city;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.city + \")\";\n    }\n}\n","hints":["Compare Strings with `equals`: `if (friend.getCity().equals(city))`.","Print `friend.getName()`, not the whole friend, and count the matches. The line `count + \" in \" + city` comes after the loop."],"tests":[{"name":"Friends in Lisbon","stdin":"","call":"ArrayList<Friend> friends = new ArrayList<>();\nfriends.add(new Friend(\"Ines\", \"Lisbon\"));\nfriends.add(new Friend(\"Tom\", \"Leeds\"));\nfriends.add(new Friend(\"Mia\", \"Lisbon\"));\nprintFrom(friends, \"Lisbon\");\n","expect":"Ines\nMia\n2 in Lisbon","hidden":false},{"name":"Friends in Leeds","stdin":"","call":"ArrayList<Friend> friends = new ArrayList<>();\nfriends.add(new Friend(\"Ines\", \"Lisbon\"));\nfriends.add(new Friend(\"Tom\", \"Leeds\"));\nfriends.add(new Friend(\"Mia\", \"Lisbon\"));\nprintFrom(friends, \"Leeds\");\n","expect":"Tom\n1 in Leeds","hidden":true},{"name":"Nobody in Oslo","stdin":"","call":"ArrayList<Friend> friends = new ArrayList<>();\nfriends.add(new Friend(\"Ines\", \"Lisbon\"));\nfriends.add(new Friend(\"Tom\", \"Leeds\"));\nprintFrom(friends, \"Oslo\");\n","expect":"0 in Oslo","hidden":true},{"name":"Four friends","stdin":"","call":"ArrayList<Friend> friends = new ArrayList<>();\nfriends.add(new Friend(\"Ari\", \"Turku\"));\nfriends.add(new Friend(\"Bea\", \"Turku\"));\nfriends.add(new Friend(\"Cai\", \"Espoo\"));\nfriends.add(new Friend(\"Dan\", \"Turku\"));\nprintFrom(friends, \"Turku\");\n","expect":"Ari\nBea\nDan\n3 in Turku","hidden":true}],"require":[],"forbid":[]}]}