jzbakos
jzbakos

Reputation: 285

ArrayList re-using single Object, instead of creating new ones

I am working on a simple program that reads a text file that contains book titles and the associated reference number. Each set of information should be turned into a Book object so that it can be sorted later on. However, in the current code, whenever a new Book should be created, it re-uses the original Book. I have added a counter to the Book class to track the amount of Book objects.

The program should create a new Book object using the book title and associated reference number. What would I change/add in order to fix this problem?

Main Class

    private static ArrayList<Book> books = new ArrayList();

    public static void main(String[] args) {
        String path = "src//booklist.txt";
        boolean endOfFile = false;

        // try/catch for reading the file
        try {
            FileReader fr = new FileReader(path);
            BufferedReader br = new BufferedReader(fr);

            while (!endOfFile) {
                String line = br.readLine();

                if (line == null) {
                    endOfFile = true;
                } else {
                    books.add(new Book(null, 0));
                    books.get(books.size() - 1).setRefNum(Integer.parseInt(line));

                    String bookTitle = br.readLine();
                    books.get(books.size() - 1).setTitle(bookTitle);
                }
                System.out.println(books.get(books.size() - 1).toString());
            }
            // Closing reader and displaying results
            br.close();
        } catch (IOException e) {
            System.out.println(e.toString());
        }
    }
}

Book Class

private String bookTitle;
private int refNum;
private int numBooks;

public Book(String title, int referenceNumber) {
    this.bookTitle = title;
    this.refNum = referenceNumber;
    this.numBooks++;
}

public String getTitle() {
    return this.bookTitle;
}

public void setTitle(String title) {
    this.bookTitle = title;
}

public int getRefNum() {
    return this.refNum;
}

public void setRefNum(int referenceNumber) {
    this.refNum = referenceNumber;
}

public int getNumBooks() {
    return this.numBooks;
}

public String toString() {
    String message = "Book Title: " + this.bookTitle
            + "\nReference #: " + this.refNum
            + "\nBook #: " + this.numBooks
            + "\n";
    return message;
}

Text Document (booktitles.txt)

1
The Adventures of Tom Sawyer
2
Huckleberry Finn
4
The Sword in the Stone
6
Stuart Little
10
Treasure Island
12
The Secret Garden
14
Alice's Adventures in Wonderland
20
Twenty Thousand Leagues Under the Sea
24
Peter Pan
26
Charlotte's Web
31
A Little Princess
32
Little Women
33
Black Beauty
35
The Merry Adventures of Robin Hood
40
Robinson Crusoe
46
Anne of Green Gables
50
Little House in the Big Woods
52
Swiss Family Robinson
54
The Lion, the Witch and the Wardrobe
56
Heidi
66
A Winkle in Time
100
Mary Poppins

Current Output

Book Title: The Adventures of Tom Sawyer
Reference #: 1
Book #: 1

Book Title: Huckleberry Finn
Reference #: 2
Book #: 1

Book Title: The Sword in the Stone
Reference #: 4
Book #: 1

Book Title: Stuart Little
Reference #: 6
Book #: 1

Book Title: Treasure Island
Reference #: 10
Book #: 1

Book Title: The Secret Garden
Reference #: 12
Book #: 1

Book Title: Alice's Adventures in Wonderland
Reference #: 14
Book #: 1

Book Title: Twenty Thousand Leagues Under the Sea
Reference #: 20
Book #: 1

Book Title: Peter Pan
Reference #: 24
Book #: 1

Book Title: Charlotte's Web
Reference #: 26
Book #: 1

Book Title: A Little Princess
Reference #: 31
Book #: 1

Book Title: Little Women
Reference #: 32
Book #: 1

Book Title: Black Beauty
Reference #: 33
Book #: 1

Book Title: The Merry Adventures of Robin Hood
Reference #: 35
Book #: 1

Book Title: Robinson Crusoe
Reference #: 40
Book #: 1

Book Title: Anne of Green Gables
Reference #: 46
Book #: 1

Book Title: Little House in the Big Woods
Reference #: 50
Book #: 1

Book Title: Swiss Family Robinson
Reference #: 52
Book #: 1

Book Title: The Lion, the Witch and the Wardrobe
Reference #: 54
Book #: 1

Book Title: Heidi
Reference #: 56
Book #: 1

Book Title: A Winkle in Time
Reference #: 66
Book #: 1

Book Title: Mary Poppins
Reference #: 100
Book #: 1

Desired Output

Book Title: The Adventures of Tom Sawyer
Reference #: 1
Book #: 1

Book Title: Huckleberry Finn
Reference #: 2
Book #: 2

Book Title: The Sword in the Stone
Reference #: 4
Book #: 3

Book Title: Stuart Little
Reference #: 6
Book #: 4

Book Title: Treasure Island
Reference #: 10
Book #: 5

Book Title: The Secret Garden
Reference #: 12
Book #: 6

Book Title: Alice's Adventures in Wonderland
Reference #: 14
Book #: 7

Book Title: Twenty Thousand Leagues Under the Sea
Reference #: 20
Book #: 8

Book Title: Peter Pan
Reference #: 24
Book #: 9

Book Title: Charlotte's Web
Reference #: 26
Book #: 10

Book Title: A Little Princess
Reference #: 31
Book #: 11

Book Title: Little Women
Reference #: 32
Book #: 12

Book Title: Black Beauty
Reference #: 33
Book #: 13

Book Title: The Merry Adventures of Robin Hood
Reference #: 35
Book #: 14

Book Title: Robinson Crusoe
Reference #: 40
Book #: 15

Book Title: Anne of Green Gables
Reference #: 46
Book #: 16

Book Title: Little House in the Big Woods
Reference #: 50
Book #: 17

Book Title: Swiss Family Robinson
Reference #: 52
Book #: 18

Book Title: The Lion, the Witch and the Wardrobe
Reference #: 54
Book #: 19

Book Title: Heidi
Reference #: 56
Book #: 20

Book Title: A Winkle in Time
Reference #: 66
Book #: 21

Book Title: Mary Poppins
Reference #: 100
Book #: 22

Upvotes: 0

Views: 42

Answers (5)

Abhinit Sinha
Abhinit Sinha

Reputation: 1

As per your current output, title is changing, but book# is not changing.

Make numBooks static. Static variables are linked with a class instead of being instances of the class, thus the same variable will be shared across all objects which are instance of the same class.

Upvotes: 0

Suresh A
Suresh A

Reputation: 1188

Replace the lines

books.add(new Book(null, 0));
books.get(books.size() -1).setRefNum(Integer.parseInt(line));

String bookTitle = br.readLine();
books.get(books.size() - 1).setTitle(bookTitle);

By

String bookTitle = br.readLine();
books.add(new Book(bookTitle,Integer.parseInt(line)));

Your problem is in the Book class with numBooks.You do not need this . You can use arrayList books and its index for the output.

Upvotes: 0

Mitesh Raval
Mitesh Raval

Reputation: 47

The counter added to Book class is not static. So it would be unique for each new instance of Book object. So it will always be one.

private int numBooks;

public Book(String title, int referenceNumber) {
    this.bookTitle = title;
    this.refNum = referenceNumber;
    this.numBooks++;
}

Do you not see multiple books added from the ArrayList books object?

System.out.println(books.get(books.size() - 1).toString());

Upvotes: 0

Jim Garrison
Jim Garrison

Reputation: 86774

I think you misunderstand the code

books.add(new Book(null, 0));
books.get(books.size() - 1).setRefNum(Integer.parseInt(line));
String bookTitle = br.readLine();
books.get(books.size() - 1).setTitle(bookTitle);

This is creating a new Book each time. However it is inefficient. Consider

Book b = new Book(null,0);
books.add(b);
b.setRefNum(Integer.parseInt(line));
String bookTitle = br.readLine();
b.setTitle(bookTitle);

Variable b is local to the loop. Even better, use the constructor

String bookTitle = br.readLine();
Book b = new Book(bookTitle,Integer.parseInt(line));
books.add(b);

As to the clarified question:

numBooks is an instance variable so there's one copy for every book. What you need is to use books.size() to retrieve the number of entries in the list. Remove numBooks from the Book class, it is not necessary.

Upvotes: 2

Scary Wombat
Scary Wombat

Reputation: 44834

use the proper values in the constructor so that a dummy book does not need to be added and subsequently got in order to be updated

String bookTitle = br.readLine();
books.add(new Book(bookTitle, Integer.parseInt(line)));

Upvotes: 0

Related Questions