{"id":"objects-with-lists-objects-in-list","slug":"objects-on-the-list","title":"Objects on the object's list","text":"The list inside an object can hold objects of your own classes too. A bookshelf holds books, and each book has a title, an author and a number of pages. That makes a program of three files:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Bookshelf shelf = new Bookshelf(\"Living room\");\n        shelf.add(new Book(\"Emma\", \"Austen\", 474));\n        shelf.add(new Book(\"Persuasion\", \"Austen\", 249));\n        shelf.add(new Book(\"Dracula\", \"Stoker\", 418));\n        shelf.printAll();\n        System.out.println(\"By Austen:\");\n        shelf.printBy(\"Austen\");\n    }\n}\n// ==== Bookshelf.java ====\nimport java.util.ArrayList;\n\npublic class Bookshelf {\n    private String room;\n    private ArrayList<Book> books;\n\n    public Bookshelf(String room) {\n        this.room = room;\n        this.books = new ArrayList<>();\n    }\n\n    public void add(Book book) {\n        this.books.add(book);\n    }\n\n    public void printAll() {\n        System.out.println(this.room + \":\");\n        for (Book book : this.books) {\n            System.out.println(book);\n        }\n    }\n\n    public void printBy(String author) {\n        for (Book book : this.books) {\n            if (book.getAuthor().equals(author)) {\n                System.out.println(book);\n            }\n        }\n    }\n}\n// ==== Book.java ====\npublic class Book {\n    private String title;\n    private String author;\n    private int pages;\n\n    public Book(String title, String author, int pages) {\n        this.title = title;\n        this.author = author;\n        this.pages = pages;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public String getAuthor() {\n        return this.author;\n    }\n\n    public int getPages() {\n        return this.pages;\n    }\n\n    public String toString() {\n        return this.title + \" by \" + this.author + \", \" + this.pages + \" pages\";\n    }\n}\n```\n\n```output\nLiving room:\nEmma by Austen, 474 pages\nPersuasion by Austen, 249 pages\nDracula by Stoker, 418 pages\nBy Austen:\nEmma by Austen, 474 pages\nPersuasion by Austen, 249 pages\n```\n\n- The list's type names the class of its objects: `ArrayList<Book>`. Only Book objects can go on it.\n- `add(Book book)` takes an object as its parameter (module 23) and puts it on the list.\n- In the loops, `book` is one Book at a time, and the shelf uses it through Book's public methods. `System.out.println(book)` calls the book's toString, and `book.getAuthor()` its getter. Writing `book.author` in Bookshelf doesn't compile, because `author` is private to Book.\n- Each class does its own job. Book knows how a book is written out, and Bookshelf knows which books it holds. `main` only makes the books and calls the shelf's methods.\n\n### The list holds references\n\nThe list doesn't hold copies of the books. Like any variable of a class type, each place on an `ArrayList<Book>` holds a reference to a Book object (module 22). So after\n\n```java\nBook emma = new Book(\"Emma\", \"Austen\", 474);\nshelf.add(emma);\n```\n\nthe variable `emma` and the shelf's list refer to the same Book. If Book had a method that changed the book, a change made through `emma` would show on the shelf too, and the other way around.\n\n### Making the object inside the method\n\nA shelf could also take a book's values and make the Book itself. With module 21's overloading, both methods can be called `add`, and Java picks the one whose parameters match:\n\n```java\npublic void add(String title, String author, int pages) {\n    this.books.add(new Book(title, author, pages));\n}\n```\n\nThen `shelf.add(\"Kindred\", \"Butler\", 264);` works too, and `main` never has to make a Book.\n","task":"A parking garage keeps a list of the cars parked in it. `Car.java` is ready: a car has a license plate and a color, with the getters `getPlate()` and `getColor()`. In `Garage.java`, add a private list of cars as an instance variable, and make it in the constructor. Then write two methods: `park(Car car)` adds the car to the list, and `printColor(String color)` prints every car of that color, one per line, in the order they were parked. The check runs:\n\n```java\nGarage garage = new Garage();\ngarage.park(new Car(\"ABC-123\", \"red\"));\ngarage.park(new Car(\"XYZ-789\", \"blue\"));\ngarage.park(new Car(\"JKL-456\", \"red\"));\ngarage.printColor(\"red\");\n```\n\nand expects:\n\n```\nABC-123 (red)\nJKL-456 (red)\n```\n","kind":"code","seed":"// ==== Garage.java ====\nimport java.util.ArrayList;\n\npublic class Garage {\n    // Add the list of cars here.\n\n    public Garage() {\n        // Make the list here.\n    }\n\n    // Write the methods park and printColor here.\n}\n\n// ==== Car.java ====\npublic class Car {\n    private String plate;\n    private String color;\n\n    public Car(String plate, String color) {\n        this.plate = plate;\n        this.color = color;\n    }\n\n    public String getPlate() {\n        return this.plate;\n    }\n\n    public String getColor() {\n        return this.color;\n    }\n\n    public String toString() {\n        return this.plate + \" (\" + this.color + \")\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Garage garage = new Garage();\n        garage.park(new Car(\"ABC-123\", \"red\"));\n        garage.park(new Car(\"XYZ-789\", \"blue\"));\n        garage.park(new Car(\"JKL-456\", \"red\"));\n        garage.printColor(\"red\");\n    }\n}\n","solution":"// ==== Garage.java ====\nimport java.util.ArrayList;\n\npublic class Garage {\n    private ArrayList<Car> cars;\n\n    public Garage() {\n        this.cars = new ArrayList<>();\n    }\n\n    public void park(Car car) {\n        this.cars.add(car);\n    }\n\n    public void printColor(String color) {\n        for (Car car : this.cars) {\n            if (car.getColor().equals(color)) {\n                System.out.println(car);\n            }\n        }\n    }\n}\n\n// ==== Car.java ====\npublic class Car {\n    private String plate;\n    private String color;\n\n    public Car(String plate, String color) {\n        this.plate = plate;\n        this.color = color;\n    }\n\n    public String getPlate() {\n        return this.plate;\n    }\n\n    public String getColor() {\n        return this.color;\n    }\n\n    public String toString() {\n        return this.plate + \" (\" + this.color + \")\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Garage garage = new Garage();\n        garage.park(new Car(\"ABC-123\", \"red\"));\n        garage.park(new Car(\"XYZ-789\", \"blue\"));\n        garage.park(new Car(\"JKL-456\", \"red\"));\n        garage.printColor(\"red\");\n    }\n}\n","hints":["The list holds Car objects: `private ArrayList<Car> cars;`, and the constructor makes it with `this.cars = new ArrayList<>();`. `park` adds the car it's given: `this.cars.add(car);`.","`printColor` goes through the cars with `for (Car car : this.cars)`, and prints a car when `car.getColor().equals(color)`."],"tests":[{"name":"Test 1","stdin":"","call":"Garage garage = new Garage();\ngarage.park(new Car(\"ABC-123\", \"red\"));\ngarage.park(new Car(\"XYZ-789\", \"blue\"));\ngarage.park(new Car(\"JKL-456\", \"red\"));\ngarage.printColor(\"red\");\n","expect":"ABC-123 (red)\nJKL-456 (red)","hidden":false},{"name":"Test 2","stdin":"","call":"Garage garage = new Garage();\ngarage.park(new Car(\"ABC-123\", \"red\"));\ngarage.park(new Car(\"XYZ-789\", \"blue\"));\ngarage.printColor(\"green\");\ngarage.printColor(\"blu\" + \"e\");\nGarage other = new Garage();\nother.printColor(\"blue\");\nSystem.out.println(\"done\");\n","expect":"XYZ-789 (blue)\ndone","hidden":true},{"name":"Test 3","stdin":"","call":"Garage garage = new Garage();\nCar van = new Car(\"VAN-001\", \"white\");\ngarage.park(van);\ngarage.park(new Car(\"CAR-002\", \"black\"));\ngarage.park(van);\ngarage.printColor(\"white\");\n","expect":"VAN-001 (white)\nVAN-001 (white)","hidden":true}],"require":[{"pattern":"\\bprivate\\s+ArrayList<Car>\\s+\\w+\\s*;","message":"Keep the cars in a private instance variable of type `ArrayList<Car>`."},{"pattern":"\\bpublic\\s+void\\s+park\\s*\\(\\s*Car\\s+\\w+\\s*\\)","message":"Write the method as `public void park(Car car)`."},{"pattern":"\\.getColor\\s*\\(\\s*\\)","message":"Ask each car for its color with `getColor()`."}],"forbid":[],"more":[{"task":"What does this program print? A train keeps its wagons on a list, and the wagons are Wagon objects that can still change after they're attached.\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Train train = new Train();\n        Wagon a = new Wagon(1);\n        Wagon b = new Wagon(2);\n        train.attach(a);\n        a.board(30);\n        train.attach(b);\n        train.attach(a);\n        b.board(12);\n        a.board(5);\n        train.print();\n        System.out.println(train.count() + \" wagons\");\n    }\n}\n// ==== Train.java ====\nimport java.util.ArrayList;\n\npublic class Train {\n    private ArrayList<Wagon> wagons;\n\n    public Train() {\n        this.wagons = new ArrayList<>();\n    }\n\n    public void attach(Wagon wagon) {\n        this.wagons.add(wagon);\n    }\n\n    public int count() {\n        return this.wagons.size();\n    }\n\n    public void print() {\n        for (Wagon wagon : this.wagons) {\n            System.out.println(wagon);\n        }\n    }\n}\n// ==== Wagon.java ====\npublic class Wagon {\n    private int number;\n    private int passengers;\n\n    public Wagon(int number) {\n        this.number = number;\n        this.passengers = 0;\n    }\n\n    public void board(int people) {\n        this.passengers = this.passengers + people;\n    }\n\n    public String toString() {\n        return \"Wagon \" + this.number + \": \" + this.passengers + \" passengers\";\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Train train = new Train();\n        Wagon a = new Wagon(1);\n        Wagon b = new Wagon(2);\n        train.attach(a);\n        a.board(30);\n        train.attach(b);\n        train.attach(a);\n        b.board(12);\n        a.board(5);\n        train.print();\n        System.out.println(train.count() + \" wagons\");\n    }\n}\n// ==== Train.java ====\nimport java.util.ArrayList;\n\npublic class Train {\n    private ArrayList<Wagon> wagons;\n\n    public Train() {\n        this.wagons = new ArrayList<>();\n    }\n\n    public void attach(Wagon wagon) {\n        this.wagons.add(wagon);\n    }\n\n    public int count() {\n        return this.wagons.size();\n    }\n\n    public void print() {\n        for (Wagon wagon : this.wagons) {\n            System.out.println(wagon);\n        }\n    }\n}\n// ==== Wagon.java ====\npublic class Wagon {\n    private int number;\n    private int passengers;\n\n    public Wagon(int number) {\n        this.number = number;\n        this.passengers = 0;\n    }\n\n    public void board(int people) {\n        this.passengers = this.passengers + people;\n    }\n\n    public String toString() {\n        return \"Wagon \" + this.number + \": \" + this.passengers + \" passengers\";\n    }\n}\n","hints":["The list holds references to the wagons, not copies. Passengers who board wagon `a` after it's attached are still in the wagon the train sees, so what counts is the total when `print()` runs.","`a` is attached twice, so the list has three places, and two of them refer to the same wagon. That wagon shows up twice, with all 35 passengers both times."],"tests":[{"name":"Output","stdin":"","expect":"Wagon 1: 35 passengers\nWagon 2: 12 passengers\nWagon 1: 35 passengers\n3 wagons","hidden":false}],"require":[],"forbid":[],"lines":["Wagon 1: 35 passengers","Wagon 2: 12 passengers","Wagon 1: 35 passengers","3 wagons"]},{"task":"An orchestra keeps a list of its musicians. `Musician.java` is ready: a musician has a name and an instrument, with the getters `getName()` and `getInstrument()`. `Orchestra.java` has the list. Write two methods in it:\n\n- `hire(String name, String instrument)` makes a new Musician of those values and adds it to the list.\n- `count(String instrument)` returns how many musicians play that instrument.\n\nThe check runs:\n\n```java\nOrchestra orchestra = new Orchestra();\norchestra.hire(\"Ines\", \"violin\");\norchestra.hire(\"Karl\", \"cello\");\norchestra.hire(\"Lena\", \"violin\");\nSystem.out.println(orchestra.count(\"violin\"));\nSystem.out.println(orchestra.count(\"flute\"));\n```\n\nand expects:\n\n```\n2\n0\n```\n","kind":"code","seed":"// ==== Orchestra.java ====\nimport java.util.ArrayList;\n\npublic class Orchestra {\n    private ArrayList<Musician> musicians;\n\n    public Orchestra() {\n        this.musicians = new ArrayList<>();\n    }\n\n    // Write the methods hire and count here.\n}\n\n// ==== Musician.java ====\npublic class Musician {\n    private String name;\n    private String instrument;\n\n    public Musician(String name, String instrument) {\n        this.name = name;\n        this.instrument = instrument;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String getInstrument() {\n        return this.instrument;\n    }\n\n    public String toString() {\n        return this.name + \", \" + this.instrument;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Orchestra orchestra = new Orchestra();\n        orchestra.hire(\"Ines\", \"violin\");\n        orchestra.hire(\"Karl\", \"cello\");\n        orchestra.hire(\"Lena\", \"violin\");\n        System.out.println(orchestra.count(\"violin\"));\n        System.out.println(orchestra.count(\"flute\"));\n    }\n}\n","solution":"// ==== Orchestra.java ====\nimport java.util.ArrayList;\n\npublic class Orchestra {\n    private ArrayList<Musician> musicians;\n\n    public Orchestra() {\n        this.musicians = new ArrayList<>();\n    }\n\n    public void hire(String name, String instrument) {\n        this.musicians.add(new Musician(name, instrument));\n    }\n\n    public int count(String instrument) {\n        int count = 0;\n        for (Musician musician : this.musicians) {\n            if (musician.getInstrument().equals(instrument)) {\n                count++;\n            }\n        }\n        return count;\n    }\n}\n\n// ==== Musician.java ====\npublic class Musician {\n    private String name;\n    private String instrument;\n\n    public Musician(String name, String instrument) {\n        this.name = name;\n        this.instrument = instrument;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String getInstrument() {\n        return this.instrument;\n    }\n\n    public String toString() {\n        return this.name + \", \" + this.instrument;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Orchestra orchestra = new Orchestra();\n        orchestra.hire(\"Ines\", \"violin\");\n        orchestra.hire(\"Karl\", \"cello\");\n        orchestra.hire(\"Lena\", \"violin\");\n        System.out.println(orchestra.count(\"violin\"));\n        System.out.println(orchestra.count(\"flute\"));\n    }\n}\n","hints":["`hire` makes the object and adds it in one line: `this.musicians.add(new Musician(name, instrument));`.","`count` goes through `this.musicians` and adds one to a counter when `musician.getInstrument().equals(instrument)`. It returns the counter after the loop."],"tests":[{"name":"Test 1","stdin":"","call":"Orchestra orchestra = new Orchestra();\norchestra.hire(\"Ines\", \"violin\");\norchestra.hire(\"Karl\", \"cello\");\norchestra.hire(\"Lena\", \"violin\");\nSystem.out.println(orchestra.count(\"violin\"));\nSystem.out.println(orchestra.count(\"flute\"));\n","expect":"2\n0","hidden":false},{"name":"Test 2","stdin":"","call":"Orchestra orchestra = new Orchestra();\nSystem.out.println(orchestra.count(\"harp\"));\nString brass = \"trum\";\norchestra.hire(\"Olle\", brass + \"pet\");\norchestra.hire(\"Pia\", \"trumpet\");\norchestra.hire(\"Quin\", \"harp\");\nSystem.out.println(orchestra.count(\"trumpet\") + \" \" + orchestra.count(\"harp\") + \" \" + orchestra.count(\"Pia\"));\n","expect":"0\n2 1 0","hidden":true},{"name":"Test 3","stdin":"","call":"Orchestra small = new Orchestra();\nOrchestra big = new Orchestra();\nsmall.hire(\"Rui\", \"oboe\");\nbig.hire(\"Sol\", \"oboe\");\nbig.hire(\"Tia\", \"oboe\");\nSystem.out.println(small.count(\"oboe\") + \" \" + big.count(\"oboe\"));\n","expect":"1 2","hidden":true}],"require":[{"pattern":"\\bpublic\\s+void\\s+hire\\s*\\(\\s*String\\s+\\w+\\s*,\\s*String\\s+\\w+\\s*\\)","message":"Write the method as `public void hire(String name, String instrument)`."},{"pattern":"\\bnew\\s+Musician\\s*\\(","message":"`hire` makes the Musician itself, with `new Musician(...)`."},{"pattern":"\\bpublic\\s+int\\s+count\\s*\\(\\s*String\\s+\\w+\\s*\\)","message":"Write the method as `public int count(String instrument)`."}],"forbid":[]}]}