Java Arena
Step 5 of 9

Printing an object that holds a list

System.out.println(shelf) calls the shelf's toString (module 18). For an object that holds a list, the list belongs in that text too. The shortest way joins the list itself to the text:

public String toString() {
    return this.room + ": " + this.books;
}

The list writes itself out in brackets, with each book's own toString and commas between them: Hallway: [Emma by Austen, 474 pages, Dracula by Stoker, 418 pages]. That's hard to read when the books' texts have commas of their own. A loop gives you full control over the text.

Building the text in a loop

This toString starts with the room and the number of books, and then adds each book on a line of its own:

Main.java
public class Main {
    public static void main(String[] args) {
        Bookshelf shelf = new Bookshelf("Living room");
        shelf.add(new Book("Emma", "Austen", 474));
        shelf.add(new Book("Persuasion", "Austen", 249));
        shelf.add(new Book("Dracula", "Stoker", 418));
        System.out.println(shelf);
        Bookshelf empty = new Bookshelf("Hallway");
        System.out.println(empty);
    }
}
Bookshelf.java
import java.util.ArrayList;

public class Bookshelf {
    private String room;
    private ArrayList<Book> books;

    public Bookshelf(String room) {
        this.room = room;
        this.books = new ArrayList<>();
    }

    public void add(Book book) {
        this.books.add(book);
    }

    public String toString() {
        if (this.books.isEmpty()) {
            return this.room + ": no books";
        }
        String text = this.room + ": " + this.books.size() + " books";
        for (Book book : this.books) {
            text = text + "\n" + book;
        }
        return text;
    }
}
Book.java
public class Book {
    private String title;
    private String author;
    private int pages;

    public Book(String title, String author, int pages) {
        this.title = title;
        this.author = author;
        this.pages = pages;
    }

    public String toString() {
        return this.title + " by " + this.author + ", " + this.pages + " pages";
    }
}
Output
Living room: 3 books
Emma by Austen, 474 pages
Persuasion by Austen, 249 pages
Dracula by Stoker, 418 pages
Hallway: no books
  • You met \n in module 20: inside a String, it's a line break. A String can hold several lines, and printing it prints each of them on its own line.
  • text starts as the first line, and each round of the loop adds a line break and one book. + book calls the book's own toString.
  • The line break goes before each book, not after it, so the text doesn't end with an empty line. println adds the last line break itself.
  • An empty shelf gets its own text, checked first with isEmpty(). Without that check it would say Hallway: 0 books, which is fine too. What an empty object says is part of designing the class.

toString only builds the text and returns it; it doesn't print anything. The caller decides what to do with it: System.out.println(shelf) prints it, and "Found: " + shelf makes a longer String of it.

Your task

Challenge 1 of 3

Aquarium.java has a name and a list of fish, and Fish.java is ready (its toString gives, for example, Finn the clownfish). Write toString for Aquarium. The first line is the aquarium's name and the number of fish, like Reef tank: 2 fish, and then each fish comes on a line of its own. There's no line break at the end of the text: println adds that. An aquarium with no fish is just Reef tank: empty. The check runs:

Aquarium tank = new Aquarium("Reef tank");
System.out.println(tank);
tank.add(new Fish("Finn", "clownfish"));
tank.add(new Fish("Coral", "blue tang"));
System.out.println(tank);

and expects:

Reef tank: empty
Reef tank: 2 fish
Finn the clownfish
Coral the blue tang

Challenge 2

What does this program print? A necklace's toString joins the colors of its beads with dashes, using an index loop.

Challenge 3

Bus.java holds the bus's line number and a list of passenger names. Write its toString: the line number, a colon, and the names in the order they boarded, as you'd write them in a sentence. Commas go between the names, except that the last two are joined with and, like Bus 42: Ada, Ben and Cleo. With one passenger, it's just Bus 42: Ada. The check prints only buses with at least one passenger:

Bus bus = new Bus(42);
bus.board("Ada");
System.out.println(bus);
bus.board("Ben");
System.out.println(bus);
bus.board("Cleo");
System.out.println(bus);

and expects:

Bus 42: Ada
Bus 42: Ada and Ben
Bus 42: Ada, Ben and Cleo