Java Arena
Step 7 of 9

Totals from the objects on the list

A class that holds a list of objects can answer questions about all of them together: how many pages the books have in all, how long they are on average, how many pages one author wrote. Each answer is a loop over the list:

Main.java
public class Main {
    public static void main(String[] args) {
        Bookshelf shelf = new Bookshelf("Study");
        shelf.add(new Book("Emma", "Austen", 474));
        shelf.add(new Book("Persuasion", "Austen", 249));
        shelf.add(new Book("Dracula", "Stoker", 418));
        shelf.add(new Book("Kindred", "Butler", 264));
        System.out.println("Pages: " + shelf.totalPages());
        System.out.println("Average: " + shelf.averagePages());
        System.out.println("By Austen: " + shelf.pagesBy("Austen"));
        Bookshelf empty = new Bookshelf("Hallway");
        System.out.println("Pages: " + empty.totalPages());
        System.out.println("Average: " + empty.averagePages());
    }
}
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 int totalPages() {
        int total = 0;
        for (Book book : this.books) {
            total = total + book.getPages();
        }
        return total;
    }

    public double averagePages() {
        if (this.books.isEmpty()) {
            return 0;
        }
        return (double) this.totalPages() / this.books.size();
    }

    public int pagesBy(String author) {
        int total = 0;
        for (Book book : this.books) {
            if (book.getAuthor().equals(author)) {
                total = total + book.getPages();
            }
        }
        return total;
    }
}
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 getAuthor() {
        return this.author;
    }

    public int getPages() {
        return this.pages;
    }
}
Output
Pages: 1405
Average: 351.25
By Austen: 723
Pages: 0
Average: 0.0
  • totalPages is the sum pattern you know, over the shelf's own list: a local variable starts at 0, and each book adds its pages to it.
  • averagePages doesn't write the loop again. It calls the object's own totalPages() with this. (module 18), and divides by the number of books. The (double) makes the division keep its decimals (module 4). Without it, 1405 / 4 would be 351.
  • The empty check comes first. With no books, the division would be 0 divided by 0, which for a double gives NaN, "not a number". Returning 0 is the choice made here, and since the method returns a double, it comes out as 0.0.
  • pagesBy is a total with a condition: only the books that match add their pages.

Counted when asked, not kept

The shelf could keep the total in an instance variable of its own, and add to it in add. But then every method that changes the list, such as one that removes books, would have to remember to change the total too, and one that forgets makes it wrong. Counting from the list each time can't go out of date: the list is always right, so the total is too.

Your task

Challenge 1 of 3

A trip is made of legs, and Leg.java is ready: a leg goes from one place to another, and getKm() returns its length in kilometers. In Trip.java, write the method totalKm(): it returns the length of the whole trip, the sum of its legs. A trip with no legs is 0 km. The check runs:

Trip trip = new Trip();
trip.add(new Leg("Harbor", "Mill", 12));
trip.add(new Leg("Mill", "Pine Hill", 30));
trip.add(new Leg("Pine Hill", "Camp", 8));
System.out.println(trip.totalKm());
System.out.println(new Trip().totalKm());

and expects:

50
0

Challenge 2

Squad.java has a method averageGoals(), but it has two bugs. For a squad whose players scored 3 and 4 goals it returns 3.0, not 3.5, and for a squad with no players it crashes. Fix it, so it returns the average with its decimals, and 0 for a squad with no players. Player.java and Main.java are ready, and when the method is fixed the program prints:

3.5
0.0

Challenge 3

A workout is a list of exercises. Exercise.java is ready: an exercise has a name, a number of minutes, and the calories it burns in a minute, with the getters getMinutes() and getCaloriesPerMinute(). In Workout.java, write three methods:

  • totalMinutes() returns the minutes of all the exercises together.
  • totalCalories() returns the calories of all the exercises together. Each exercise burns its minutes times its calories per minute.
  • averageMinutes() returns the average length of an exercise as a double, or 0 for a workout with no exercises.

The check runs:

Workout workout = new Workout();
workout.add(new Exercise("rowing", 20, 8));
workout.add(new Exercise("cycling", 15, 7));
workout.add(new Exercise("stretching", 10, 3));
System.out.println(workout.totalMinutes());
System.out.println(workout.totalCalories());
System.out.println(workout.averageMinutes());
System.out.println(new Workout().averageMinutes());

and expects:

45
295
15.0
0.0