{"id":"lists-of-objects-several-values","slug":"several-values-each","title":"Several values for each object","text":"Most objects hold more than one value, and their constructors take several parameters. To create them from the user's input, the loop reads the values one after the other. The name comes first, because the empty line that ends the input comes where a name would:\n\n```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<Pet> pets = new ArrayList<>();\n\n        while (true) {\n            String name = scanner.nextLine();\n            if (name.isEmpty()) {\n                break;\n            }\n            int age = Integer.valueOf(scanner.nextLine());\n            pets.add(new Pet(name, age));\n        }\n\n        for (Pet pet : pets) {\n            System.out.println(pet);\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```input\nRex\n4\nMisty\n2\nKiwi\n11\n\n```\n\n```output\nRex, 4 years old\nMisty, 2 years old\nKiwi, 11 years old\n```\n\n- Each round reads a name and checks it first. Only when there is a pet does the program read its age, with `Integer.valueOf(scanner.nextLine())`.\n- `new Pet(name, age)` gives the values in the order of the constructor's parameters, `Pet(String name, int age)`. `new Pet(age, name)` doesn't compile, since the first parameter must be a String.\n- The values are needed only to create the object, so they can live in variables that last one round.\n\n### Several values on one line\n\nData often comes with all of an object's values on one line, like `Rex,4`. Then each round reads one line and splits it, as in module 16:\n\n```java\nwhile (true) {\n    String line = scanner.nextLine();\n    if (line.isEmpty()) {\n        break;\n    }\n    String[] parts = line.split(\",\");\n    pets.add(new Pet(parts[0], Integer.valueOf(parts[1])));\n}\n```\n\nThe constructor doesn't care where its values come from: typed on lines of their own, split from one line, or written in the program.\n","task":"A cinema takes bookings. `Booking.java` is ready. Read the bookings: for each one, the name of the person and then the row number. The input ends with an empty line where the next name would be. Create a `Booking` for each and add it to the list `bookings`, and then print every booking. For the input `Ines`, `12`, `Tom`, `3` and an empty line, the program prints:\n\n```\nInes: row 12\nTom: row 3\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<Booking> bookings = new ArrayList<>();\n\n    }\n}\n\n// ==== Booking.java ====\npublic class Booking {\n    private String name;\n    private int row;\n\n    public Booking(String name, int row) {\n        this.name = name;\n        this.row = row;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getRow() {\n        return this.row;\n    }\n\n    public String toString() {\n        return this.name + \": row \" + this.row;\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<Booking> bookings = new ArrayList<>();\n\n        while (true) {\n            String name = scanner.nextLine();\n            if (name.isEmpty()) {\n                break;\n            }\n            int row = Integer.valueOf(scanner.nextLine());\n            bookings.add(new Booking(name, row));\n        }\n\n        for (Booking booking : bookings) {\n            System.out.println(booking);\n        }\n    }\n}\n\n// ==== Booking.java ====\npublic class Booking {\n    private String name;\n    private int row;\n\n    public Booking(String name, int row) {\n        this.name = name;\n        this.row = row;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getRow() {\n        return this.row;\n    }\n\n    public String toString() {\n        return this.name + \": row \" + this.row;\n    }\n}\n","hints":["Read the name and check it with `isEmpty()` first. Only after that, read the row: `int row = Integer.valueOf(scanner.nextLine());`.","`bookings.add(new Booking(name, row));` ends each round. Print the bookings with a for-each loop after the reading loop."],"tests":[{"name":"Test 1","stdin":"Ines\n12\nTom\n3\n\n","expect":"Ines: row 12\nTom: row 3","hidden":false},{"name":"Test 2","stdin":"Ada\n1\nBen\n20\nCleo\n7\n\n","expect":"Ada: row 1\nBen: row 20\nCleo: row 7","hidden":true},{"name":"Test 3","stdin":"Dev\n15\n\n","expect":"Dev: row 15","hidden":true}],"require":[{"pattern":"new\\s+Booking\\s*\\(","message":"Create each booking with `new Booking(name, row)`."}],"forbid":[],"more":[{"task":"`Main.java` reads podcasts, a title and then how many episodes the podcast has, until the title is an empty line. It doesn't compile yet, because `Podcast` only takes a title. Change `Podcast` so that its constructor takes the title and the number of episodes, the object keeps both, and a podcast prints like `Night Sky (12 episodes)`. For the input `Night Sky`, `12`, `Word Play`, `40` and an empty line, the program prints:\n\n```\nNight Sky (12 episodes)\nWord Play (40 episodes)\n```\n","kind":"code","seed":"// ==== Podcast.java ====\npublic class Podcast {\n    private String title;\n\n    public Podcast(String title) {\n        this.title = title;\n    }\n\n    public String toString() {\n        return this.title;\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<Podcast> podcasts = new ArrayList<>();\n\n        while (true) {\n            String title = scanner.nextLine();\n            if (title.isEmpty()) {\n                break;\n            }\n            int episodes = Integer.valueOf(scanner.nextLine());\n            podcasts.add(new Podcast(title, episodes));\n        }\n\n        for (Podcast podcast : podcasts) {\n            System.out.println(podcast);\n        }\n    }\n}\n","solution":"// ==== Podcast.java ====\npublic class Podcast {\n    private String title;\n    private int episodes;\n\n    public Podcast(String title, int episodes) {\n        this.title = title;\n        this.episodes = episodes;\n    }\n\n    public String toString() {\n        return this.title + \" (\" + this.episodes + \" episodes)\";\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<Podcast> podcasts = new ArrayList<>();\n\n        while (true) {\n            String title = scanner.nextLine();\n            if (title.isEmpty()) {\n                break;\n            }\n            int episodes = Integer.valueOf(scanner.nextLine());\n            podcasts.add(new Podcast(title, episodes));\n        }\n\n        for (Podcast podcast : podcasts) {\n            System.out.println(podcast);\n        }\n    }\n}\n","hints":["Three changes in `Podcast`: a new object variable `private int episodes;`, a second constructor parameter `int episodes` that's stored with `this.episodes = episodes;`, and a new `toString`.","`return this.title + \" (\" + this.episodes + \" episodes)\";`"],"tests":[{"name":"Test 1","stdin":"Night Sky\n12\nWord Play\n40\n\n","expect":"Night Sky (12 episodes)\nWord Play (40 episodes)","hidden":false},{"name":"Test 2","stdin":"Deep Dive\n3\n\n","expect":"Deep Dive (3 episodes)","hidden":true},{"name":"System.out.println(new Podcast(\"Short Talks\", 150));","stdin":"","call":"System.out.println(new Podcast(\"Short Talks\", 150));\n","expect":"Short Talks (150 episodes)","hidden":true}],"require":[],"forbid":[]},{"task":"Each line of the input is a trip: a city and the number of days, separated by a comma, like `Oslo,5`. The input ends with an empty line. `Trip.java` is ready. Read the lines, split each one and add a `Trip` to the list `trips`. Then print every trip, and last `Total: ` with the days of all the trips added up. For the input `Oslo,5`, `Rome,3`, `Lima,4` and an empty line, the program prints:\n\n```\nOslo, 5 days\nRome, 3 days\nLima, 4 days\nTotal: 12 days\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<Trip> trips = new ArrayList<>();\n\n    }\n}\n\n// ==== Trip.java ====\npublic class Trip {\n    private String city;\n    private int days;\n\n    public Trip(String city, int days) {\n        this.city = city;\n        this.days = days;\n    }\n\n    public String getCity() {\n        return this.city;\n    }\n\n    public int getDays() {\n        return this.days;\n    }\n\n    public String toString() {\n        return this.city + \", \" + this.days + \" days\";\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<Trip> trips = new ArrayList<>();\n\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.isEmpty()) {\n                break;\n            }\n            String[] parts = line.split(\",\");\n            trips.add(new Trip(parts[0], Integer.valueOf(parts[1])));\n        }\n\n        int total = 0;\n        for (Trip trip : trips) {\n            System.out.println(trip);\n            total += trip.getDays();\n        }\n        System.out.println(\"Total: \" + total + \" days\");\n    }\n}\n\n// ==== Trip.java ====\npublic class Trip {\n    private String city;\n    private int days;\n\n    public Trip(String city, int days) {\n        this.city = city;\n        this.days = days;\n    }\n\n    public String getCity() {\n        return this.city;\n    }\n\n    public int getDays() {\n        return this.days;\n    }\n\n    public String toString() {\n        return this.city + \", \" + this.days + \" days\";\n    }\n}\n","hints":["`String[] parts = line.split(\",\");` gives the city in `parts[0]` and the days, as text, in `parts[1]`. `Integer.valueOf(parts[1])` makes a number of them.","In the loop that prints the trips, also add up `trip.getDays()`. Print the total after that loop."],"tests":[{"name":"Test 1","stdin":"Oslo,5\nRome,3\nLima,4\n\n","expect":"Oslo, 5 days\nRome, 3 days\nLima, 4 days\nTotal: 12 days","hidden":false},{"name":"Test 2","stdin":"Cairo,10\n\n","expect":"Cairo, 10 days\nTotal: 10 days","hidden":true},{"name":"Test 3","stdin":"Kyiv,2\nPerth,21\nQuito,6\nBern,3\n\n","expect":"Kyiv, 2 days\nPerth, 21 days\nQuito, 6 days\nBern, 3 days\nTotal: 32 days","hidden":true}],"require":[{"pattern":"\\.split\\s*\\(","message":"Split each line with `split(\",\")`."},{"pattern":"new\\s+Trip\\s*\\(","message":"Create a `Trip` object for each line."}],"forbid":[]}]}