{"id":"lists-of-objects-from-input","slug":"objects-from-input","title":"Objects from the user's input","text":"The objects in a list don't have to be written into the program. A loop can read what the user types and create an object from each line. Here the user types tasks, one per line, and an empty line when there are no more:\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<Task> tasks = new ArrayList<>();\n\n        while (true) {\n            String description = scanner.nextLine();\n            if (description.isEmpty()) {\n                break;\n            }\n            tasks.add(new Task(description));\n        }\n\n        tasks.get(0).markDone();\n        System.out.println(tasks.size() + \" tasks\");\n        for (Task task : tasks) {\n            System.out.println(task);\n        }\n    }\n}\n// ==== Task.java ====\npublic class Task {\n    private String description;\n    private boolean done;\n\n    public Task(String description) {\n        this.description = description;\n        this.done = false;\n    }\n\n    public void markDone() {\n        this.done = true;\n    }\n\n    public String toString() {\n        if (this.done) {\n            return \"[x] \" + this.description;\n        }\n        return \"[ ] \" + this.description;\n    }\n}\n```\n\n```input\nwater the plants\ncall the dentist\nbuy stamps\n\n```\n\n```output\n3 tasks\n[x] water the plants\n[ ] call the dentist\n[ ] buy stamps\n```\n\n- The loop is the `while (true)` loop you know: read a line, stop at the empty line, and otherwise use the line.\n- `new Task(description)` creates a new object in every round, and `add` puts it in the list. The variable `description` lasts only one round, but the list still refers to every object.\n- `tasks.get(0).markDone()` changes the first object in the list. Like the list variables in module 14, the list refers to its objects: nothing is copied, so `tasks.get(0)` is the very task that was added, and the change shows when the list is printed. (With no tasks at all, `get(0)` would crash; a real program would check `tasks.isEmpty()` first.)\n\n### Check before you create\n\nThe `if` with `break` comes before `new Task(...)`. If `add` came first, the empty line would become a task of its own: the list would end with a task that has no description, and the count would be one too high.\n\n### Input that ends with an empty line\n\nThe input of a program like this one ends with an empty line: that's what stops the loop. The task cards show it as \"(an empty line)\". When you run such a program with your own input, end it with an empty line too. If the input runs out before it, `nextLine()` has nothing left to read and the program stops with an error.\n","task":"`NameTag.java` is ready. Read names until an empty line. For each name, create a `NameTag` and add it to the list `tags`. Then print the number of tags, followed by ` name tags`, and every tag with a for-each loop. For the input `Ines`, `Tom` and an empty line, the program prints:\n\n```\n2 name tags\nHello, my name is Ines\nHello, my name is Tom\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<NameTag> tags = new ArrayList<>();\n\n    }\n}\n\n// ==== NameTag.java ====\npublic class NameTag {\n    private String name;\n\n    public NameTag(String name) {\n        this.name = name;\n    }\n\n    public String toString() {\n        return \"Hello, my name is \" + this.name;\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<NameTag> tags = new ArrayList<>();\n\n        while (true) {\n            String name = scanner.nextLine();\n            if (name.isEmpty()) {\n                break;\n            }\n            tags.add(new NameTag(name));\n        }\n\n        System.out.println(tags.size() + \" name tags\");\n        for (NameTag tag : tags) {\n            System.out.println(tag);\n        }\n    }\n}\n\n// ==== NameTag.java ====\npublic class NameTag {\n    private String name;\n\n    public NameTag(String name) {\n        this.name = name;\n    }\n\n    public String toString() {\n        return \"Hello, my name is \" + this.name;\n    }\n}\n","hints":["A `while (true)` loop reads a name, stops with `break` when `name.isEmpty()`, and otherwise runs `tags.add(new NameTag(name));`.","After the loop, print `tags.size() + \" name tags\"`, and then each tag with `for (NameTag tag : tags)`."],"tests":[{"name":"Test 1","stdin":"Ines\nTom\n\n","expect":"2 name tags\nHello, my name is Ines\nHello, my name is Tom","hidden":false},{"name":"Test 2","stdin":"Ada\nBen\nCleo\nDev\n\n","expect":"4 name tags\nHello, my name is Ada\nHello, my name is Ben\nHello, my name is Cleo\nHello, my name is Dev","hidden":true},{"name":"Test 3","stdin":"\n","expect":"0 name tags","hidden":true}],"require":[{"pattern":"new\\s+NameTag\\s*\\(","message":"Create a tag for each name with `new NameTag(name)`."},{"pattern":"for\\s*\\(\\s*NameTag\\s+\\w+\\s*:","message":"Print the tags with a for-each loop: `for (NameTag tag : tags)`."}],"forbid":[],"more":[{"task":"Racers sign up for a race by name, and each one gets the next start number: the first racer gets 1, the second 2, and so on. `Racer.java` is ready. Read names until an empty line, create a `Racer` for each name with its start number, and add it to the list `racers`. Then print every racer. For the input `Ines`, `Tom`, `Mia` and an empty line, the program prints:\n\n```\n#1 Ines\n#2 Tom\n#3 Mia\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<Racer> racers = new ArrayList<>();\n\n    }\n}\n\n// ==== Racer.java ====\npublic class Racer {\n    private String name;\n    private int number;\n\n    public Racer(String name, int number) {\n        this.name = name;\n        this.number = number;\n    }\n\n    public String toString() {\n        return \"#\" + this.number + \" \" + this.name;\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<Racer> racers = new ArrayList<>();\n\n        while (true) {\n            String name = scanner.nextLine();\n            if (name.isEmpty()) {\n                break;\n            }\n            racers.add(new Racer(name, racers.size() + 1));\n        }\n\n        for (Racer racer : racers) {\n            System.out.println(racer);\n        }\n    }\n}\n\n// ==== Racer.java ====\npublic class Racer {\n    private String name;\n    private int number;\n\n    public Racer(String name, int number) {\n        this.name = name;\n        this.number = number;\n    }\n\n    public String toString() {\n        return \"#\" + this.number + \" \" + this.name;\n    }\n}\n","hints":["Before a racer is added, the list holds all the racers before it. So the next number is `racers.size() + 1`. (A counter variable works too.)","`racers.add(new Racer(name, racers.size() + 1));` inside the reading loop, and a for-each loop after it to print."],"tests":[{"name":"Test 1","stdin":"Ines\nTom\nMia\n\n","expect":"#1 Ines\n#2 Tom\n#3 Mia","hidden":false},{"name":"Test 2","stdin":"Ada\n\n","expect":"#1 Ada","hidden":true},{"name":"Test 3","stdin":"Ben\nCleo\nDev\nEli\nFay\n\n","expect":"#1 Ben\n#2 Cleo\n#3 Dev\n#4 Eli\n#5 Fay","hidden":true}],"require":[],"forbid":[]},{"task":"This program should read wishes until an empty line, then print how many there are and each one. But for the input `a bike`, `a kite` and an empty line, it says `3 wishes`, and its last line is `I wish for` with nothing after it. Fix it, so the program prints:\n\n```\n2 wishes\nI wish for a bike\nI wish for a kite\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<Wish> wishes = new ArrayList<>();\n\n        while (true) {\n            String thing = scanner.nextLine();\n            wishes.add(new Wish(thing));\n            if (thing.isEmpty()) {\n                break;\n            }\n        }\n\n        System.out.println(wishes.size() + \" wishes\");\n        for (Wish wish : wishes) {\n            System.out.println(wish);\n        }\n    }\n}\n\n// ==== Wish.java ====\npublic class Wish {\n    private String thing;\n\n    public Wish(String thing) {\n        this.thing = thing;\n    }\n\n    public String toString() {\n        return \"I wish for \" + this.thing;\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<Wish> wishes = new ArrayList<>();\n\n        while (true) {\n            String thing = scanner.nextLine();\n            if (thing.isEmpty()) {\n                break;\n            }\n            wishes.add(new Wish(thing));\n        }\n\n        System.out.println(wishes.size() + \" wishes\");\n        for (Wish wish : wishes) {\n            System.out.println(wish);\n        }\n    }\n}\n\n// ==== Wish.java ====\npublic class Wish {\n    private String thing;\n\n    public Wish(String thing) {\n        this.thing = thing;\n    }\n\n    public String toString() {\n        return \"I wish for \" + this.thing;\n    }\n}\n","hints":["Follow the empty line through the loop: it's added to the list as a wish before the `if` stops the loop.","Move `wishes.add(new Wish(thing));` below the `if`, so the loop stops before the empty line becomes a wish."],"tests":[{"name":"Test 1","stdin":"a bike\na kite\n\n","expect":"2 wishes\nI wish for a bike\nI wish for a kite","hidden":false},{"name":"Test 2","stdin":"a boat\n\n","expect":"1 wishes\nI wish for a boat","hidden":true},{"name":"Test 3","stdin":"\n","expect":"0 wishes","hidden":true}],"require":[],"forbid":[]}]}