I'm new to Java so sorry for all the mistakes!
Im creating a Library program consisting of 4 classes: Library, Book, BookInterface & Patron.
In the Book class I have a method that prints out all the books in the library and their status' (in or out). Instead I keep getting something like this:
Great Gatsby: null
Withering Heights: null
Does it have something to do with the setStatus() method?
Every time a user adds a new book, it creates a new Book instance and then I do setStatus("IN"). So how come it is not saving and instead printing out null?
Thank you very much for the help!!
Book class:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Book implements BookInterface
{
Scanner input = new Scanner(System.in);
static ArrayList <String> UserList = new ArrayList<String>();
static ArrayList <String> BookList = new ArrayList <String> (); //display just titles// use when checking out books
static ArrayList <String> OrigBookList = new ArrayList <String> (); //keep track of all titles ever entered
public String title;
public String author;
public String book;
public boolean checkIn;
private String status;
private String borrower;
public Book(String t, String a)
{
title = t;
author = a;
}
//constructor create new book
public Book(String newTitle)
{
title = newTitle;
}
public String toString()
{
return title + " " + author;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getAuthor()
{
return author;
}
public void setAuthor(String author)
{
this.author = author;
}
public String getStatus(String book)
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public void setBorrower(String borrower)
{
this.borrower = borrower;
}
public String getBorrower(String checkPatron)
{
return borrower;
}
public String getBook(String checkPatron)
{
return book;
}
public void setBook(String bookCheckOut)
{
this.book = bookCheckOut;
}
public void addBook()
{
Scanner input = new Scanner(System.in);
Scanner inputread = new Scanner(System.in);
System.out.print("Enter book title: ");
String title1 = inputread.nextLine();
Scanner input1 = new Scanner(System.in);
System.out.print("Enter book author: ");
String author1 = inputread.next();
Book fullBook = new Book(title1, author1); //create constructor w/ title & author
Book book1 = new Book(title1); //constructor w/ just title to be used to display all books
OrigBookList.add(title1);
book1.setStatus("IN");
System.out.println("-----------------------------------------------");
System.out.println("-----" + title1 + " is now in the library!-----");
System.out.println("-----------------------------------------------");
}
public void editBook()
{
Scanner inputread = new Scanner(System.in);
System.out.println("Enter original book title: ");
String origTitle = inputread.nextLine();
System.out.println("Enter edited book title: ");
String editedTitle = inputread.nextLine();
Collections.replaceAll(Book.UserList, origTitle, editedTitle);
System.out.println("------------------------------------------------------");
System.out.println(origTitle + " has been changed to " + editedTitle + "!");
System.out.println("------------------------------------------------------");
}
public void libraryInventory()
{
System.out.println("------------------ Library Inventory: ---------------");
for(int i =0; i<= OrigBookList.size()-1; i++)
{
//Book Title: checked in/out
System.out.println(OrigBookList.get(i) + ":" + getStatus(OrigBookList.get(i)));
}
System.out.println("-----------------------------------------------------");
}
}
getStatus(OrigBookList.get(i)) ignores the parameter you pass to it and just returns the status of the Book for which you called the libraryInventory method. Obviously, that Book instance doesn't have the status field initialized, but even if it did, it will give you the status of just one Book.
Instead of having a static list of book titles (static ArrayList <String>), perhaps you should maintain a list of the books themselves (static ArrayList <Book>), or even better, put that list in a separate class (you can call it Library).
Methods such as libraryInventory shouldn't be in the Book class (and if you insist on keeping them in the Book class, make them static, since they don't refer to a single Book instance).
Your whole program seems to be running inside an instance of the class Book. In it, you are making and discarding new instances of Book, called fullBook and book1, and for fullBook you set its status. When you call getStatus on the main Book in your program, it just returns its own status, which was never set to anything.
If you want to save a sequence of instances of Book, you need to put the instances somewhere, not just instantiate them and then add the title to a list.
Related
Background information: I have a text file of books filled with their respected information (ex: title, publisher, pageCount). I have successfully created an inheritance hierarchy with all the correct implementations, get/setters, and toString methods. The inheritance hierarchy essentially looks like this (code will be provided further below):
Book
title
publisher
pageCount
FictionBook inherits Book
author
genre
NonFictionBook inherits Book
language
Dictionary inherits NonFictionBook
versionNumber
CookBook inherits NonFictionBook
topic
Novel inherits FictionBook
isPartOfASeries (i.e. Y or N)
GraphicNovel inherits FictionBook
illustrator
The text file looks like this:
My problem: I have been following this example: https://beginnersbook.com/2013/12/java-arraylist-of-object-sort-example-comparable-and-comparator/ but I do not fully understand how to use the compareTo method and further accurately sort the info into the correct classes. In my current code, my compareTo method seems to be printing the whole string and not accurately sorting it. I will provide all related code, output, and the parent class for the inheritance hierarchy class for better understanding.
My Question: How do I use the compareTo and collections.sort methods to accurately sort and print out my data. I have been stuck on this for a while so any guidance to me solving and learning this is appreciated!
Book Class (The Parent Class w/ Comparator and compare method):
public abstract class Book implements Comparable {
public String title;
public String publisher;
public int pageCount;
public Book(String title, String publisher, int pageCount) {
this.title = title;
this.publisher = publisher;
this.pageCount = pageCount;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public static Comparator<Book> bookTitleComp = new Comparator<Book>() {
public int compare(Book b1, Book b2) {
String bookTitle1 = b1.getTitle().toUpperCase();
String bookTitle2 = b2.getTitle().toUpperCase();
return bookTitle1.compareTo(bookTitle2);
}
};
// #Override
public String toString() {
return "Book " + "title: " + title + ", publisher: " + publisher + ", pageCount: " + pageCount;
}
}
Main Class (Here I am reading in my text file, sorting by the first number in the text field, so 1 = Dictionary, 2=Cookbook, 3=Novel, 4=GraphicNovel, and trying to print my compare method: last 4 lines)
ArrayList<Book> library = new ArrayList<Book>(); //Initialize ArrayList library
//Read text file in
FileReader fr = null;
try {
fr = new FileReader("library.txt"); //Reads in text file
} catch (FileNotFoundException ex) {
Logger.getLogger(GUICommandFunctions.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader reader = new BufferedReader(fr);
try {
String line;
while((line=reader.readLine())!=null) {
System.out.println(line);
String[] splitLine = line.split(", ");
if("1".equals(splitLine[0])) {
library.add(new Dictionary(splitLine[1], splitLine[2], Integer.parseInt(splitLine[3]), splitLine[4], splitLine[5]));
} else if ("2".equals(splitLine[0])) {
library.add(new Cookbook(splitLine[1], splitLine[2], Integer.parseInt(splitLine[3]), splitLine[4], splitLine[5]));
} else if ("3".equals(splitLine[0])) {
library.add(new Novel(splitLine[1], splitLine[2], Integer.parseInt(splitLine[3]), splitLine[4], splitLine[5], splitLine[6]));
}else if ("4".equals(splitLine[0])) {
library.add(new GraphicNovel(splitLine[1], splitLine[2], Integer.parseInt(splitLine[3]), splitLine[4], splitLine[5], splitLine[6]));
}
}
} catch (IOException ex) {
Logger.getLogger(GUICommandFunctions.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Book title sorting: ");
Collections.sort(library, Book.bookTitleComp);
for(Book str: library) {
System.out.println(str);
}
Current Output:
Book title sorting:
Novel isPartOfSeries: N
Novel isPartOfSeries: N
Cookbook topic: French Cooking
GraphicNovel illustrator: Neil Gaiman
Cookbook topic: Asian Cooking
Novel isPartOfSeries: Y
Novel isPartOfSeries: Y
Cookbook topic: Keto Cooking
Novel isPartOfSeries: Y
Dictionary version number: 4
Dictionary version number: 2
GraphicNovel illustrator: Dave Gibbons
GraphicNovel illustrator: Pia Guerra
BUILD SUCCESSFUL (total time: 3 seconds)
follow the below example
import java.util.*;
public class CustomObject {
private String customProperty;
public CustomObject(String property) {
this.customProperty = property;
}
public String getCustomProperty() {
return this.customProperty;
}
public static void main(String[] args) {
ArrayList<Customobject> list = new ArrayList<>();
list.add(new CustomObject("Z"));
list.add(new CustomObject("A"));
list.add(new CustomObject("B"));
list.add(new CustomObject("X"));
list.add(new CustomObject("Aa"));
list.sort((o1, o2) -> o1.getCustomProperty().compareTo(o2.getCustomProperty()));
for (CustomObject obj : list) {
System.out.println(obj.getCustomProperty());
}
}
}
In this java program I am trying to search if an ISBN number exists in the "Book" type array or not. But when I try to implement the method and display the output, I am getting an error which says " The method searchBook(Book, String) is undefined for the type Book". The <-- HERE comment shows where the error pops up. I do not understand how to rectify this error and any help will be appreciated. Thank you.
The driver class is : QuizMain
public class User {
int ID;
String name;
String email;
int age;
String isbn;
void searchBook(Book[] b, String isbn) {
for (int i =0;i<6;i++) {
if (b[i].ISBN == isbn) {
System.out.println(b[i].title);
} else {
System.out.println("ISBN Not Found");
}
}
}
}
public class Book {
String title;
String author;
String ISBN;
float rating;
int noOfDays;
void displayBookDetails() {
System.out.println("Title\tAuthor\tISBN\tRating"+this.title +this.author + this.ISBN +this.rating);
}
// book constructor
public Book(String title, String author, String ISBN, float rating) {
this.title = title;
this.author = author;
this.ISBN = ISBN;
this.rating = rating;
}
}
public class QuizMain {
public static void main(String[] args) {
Book[] arr = new Book[6];
arr[0] = new Book("Vincent la la ","king","2194-5357",6.5f);
arr[1] = new Book("A man of wisdom","henry","2193-4567",3.2f);
arr[2] = new Book("Apple Garden","timorthy","2104-3080",1.2f);
arr[3] = new Book("Sherlock","Arthur","2165-0932",5.5f);
arr[4] = new Book("Hello John","Tarnia","2134-2342",1.5f);
arr[5] = new Book("Tarzan","Martin","2111-0564",4.2f);
for(int i =0;i<arr.length;i++) {
arr[i].searchBook(arr[i], "2165-0932"); // <-- HERE
}
arr.searchBook(arr[5], "2165-0932"); // <-- HERE
}
}
In the User class the searchBook(Book[] b, String isbn) method accepts an array of Book and a String isbn value.
But while calling this method you are passing only one Book object instead of array of Book.
Move the searchBook implementation to QuizMain class and call this by passing array of Book as shown below for a workaround .
searchBook(arr, "2165-0932");
May be you need to concentrate on designing the class and its behavior.
There are two problems in your code. First one your searchBook function expecting Book type array and string but you are passing it one Book instant i.e arr[i] with string and secondly you have define the searchBook() function in User class and using it with object of Book class. Move your function to Book class. Even you don't need that function in any of Book or User class you can simply define static function searchBook(Book[] books, String isbn) inside your QuizMain class and call it like
searchBook(arr,"8344-3452")
Instead of using boolean to see if a book was checked out I thought using a string to represent it was what I wanted but when I call the method to checkout a book the string applies to the entire array list of book objects. How can i change the status of just that book ?
import java.util.*;
public class Library
{
String owner;
int numBooks;
boolean isCheckedOut;
String status = "false";
ArrayList<Book> bookList = new ArrayList<Book>();
public void addBook(Book b)
{
bookList.add(b);
}
public String checkout(Book c) {
status = "true";
return status;
}
public Library(String o)
{
owner = o;
}
public String toString()
{
String s = "Owner: \t" + owner + "\nSize: \t" +
bookList.size()+"\nBooks: \t";
for( int i = 0;i < bookList.size();i++)
{
String title = bookList.get(i).getTitle();
//System.out.println(title);
s+="\n\t\t\t" +title +" Checked out: " + status; //bookList.get(i).getStatus();
}
return s;
}
public static void main(String [] args)
{
Library l = new Library("Jeremiah");
System.out.println(l);
}
}
i
public class Mainn
{
public static void main(String [] args)
{
Book book1 = new Book("Aambi","Aisney","Aalt","1942",1453);
Book book2 = new Book("Bambi","Bisney","Balt","1942",1453);
Book book3 = new Book("Cambi","Cisney","Calt","1942",1453);
Book book4 = new Book("Dambi","Disney","Dalt","1942",1453);
Book book5 = new Book("Eambi","Eisney","Ealt","1942",1453);
Book book6 = new Book("Fambi","Fisney","Falt","1942",1453);
Book book7 = new Book("Gambi","Gisney","Galt","1942",1453);
Book book8 = new Book("Hambi","Hisney","Halt","1942",1453);
Book book9 = new Book("Iambi","Iisney","Ialt","1942",1453);
Book book10 = new Book("Jambi","Jisney","Jalt","1942",1453);
Book book11 = new Book("Kambi","Kisney","Kalt","1942",1453);
Library l = new Library("Jeremiah");
// l.addBook(new Book("Xambi","Xisney","Xalt","1579",765));
l.addBook(book1);
l.addBook(book2);
l.addBook(book3);
l.addBook(book4);
l.addBook(book5);
l.addBook(book6);
l.addBook(book7);
l.addBook(book8);
l.addBook(book9);
l.addBook(book10);
l.addBook(book11);
// this changes all of the values to true instead of just this one
l.checkout(book1);
l.checkout(book11);
l.addBook(book1);
System.out.println(l);
}
}
You are storing the status against the Library, and not against each Book. To check out a single book, you'll need to put the status field into the book, and then set the book's status:
public class Book
{
public String status;
// etc...
}
public String checkout(Book c) {
c.status = "true";
return c.status;
}
Storing a boolean value as a string isn't usually the best idea - you'd normally be better off using an actual Boolean field for this.
A cleaner (more object oriented) implementation would look something like:
public class Book {
private boolean checkedOut = false;
public void checkout() {
checkedOut = true;
}
public void checkin() {
checkedOut = false;
}
public boolean isCheckedOut() {
return checkedOut;
}
}
This keeps the logic for managing a book with the book itself, and would allow you to easily add validation, such as preventing checkout if the field is already set to true.
So a big problem I'm seeing here is that you don't have the "Status" attribute on each book separately, you just have the one status String for the entire library.
It's not storing a status for each book.
What you could do is add an attribute called status to the Book class, and in the method where you check it out, you would set that to false. When printing them, you would print the status of each book by accessing this variable within each book object.
I think, the following piece of code help you:
public class Book {
private boolean status;
public boolean getStatus() {
return this.status;
}
public void setStatus(boolean status) {
this.status = status;
}
}
public class Library {
public boolean checkout(Book c) {
c.setStatus(true);
return c.getStatus();
}
}
And I advice to you use a boolean primitive type instead a String object.
I'm tasked by a newbie Java tutorial to do the below
In the user class:
Create a method called readBook(Book book)
readBook should print, "<User> read <title>"
In the BookRunner
For each book, create an author.
Separately, create another user and call the readBook method on that user, passing in one of the created books
The below is my code:
public class Ex1_BookRunner {
public static void main(String[] args) {
Book firstBook = new Book("One Piece", "Oda-Sensei", 100, 123456);
Book secondBook = new Book("Life of Megan Fox", "Micheal Bay", 200, 928765);
}
}
public class User {
public String name;
public int age;
public String location;
public Book title;
public String toString() {
String description1 = "Name:" + name + " Age:"+ age + " Location:" + location;
return description1;
}
public void readBook(Book book) {
System.out.println(name + " read " + title.title);
}
}
public class Book {
public String title;
public User author;
public int numPages;
public int isbn;
public Book(String title, User author, int numPages, int isbn) {
this.title = title;
this.author = author;
this.numPages = numPages;
this.isbn = isbn;
}
public String toString() {
String description = "Title:" + title + "Author"+ author.name + "Num. of pages" + numPages + "ISBN" + isbn;
return description;
}
}
I'm having problems even understanding what the question wants me to do. I've got the below questions
What does the question mean by getting me to print <User> read <title> with the readBook method? Did I interpret the question correctly with the way I set up the readBook method?
What should be the correct code in the method?
I have problems getting the author created, as I get the error The constructor Book(String, String, int, int) is undefined and the Eclipse IDE wants me to change the constructor in Book from (String, User, int, int) to (String, String, int, int). Experiments with User."Oda-Sensei", "Oda-Sensei".name, "Oda-Sensei.User" all give me the notice that the variable I'm introducing cannot be resolved.
From the questioning, it sounds like authors are users. Your constructor calls in the main method are passing in strings, hence your error about the constructor. If authors are users, then you should change your calls from:
public static void main(String[] args) {
Book firstBook = new Book("One Piece", "Oda-Sensei", 100, 123456);
Book secondBook = new Book("Life of Megan Fox", "Micheal Bay", 200, 928765);
}
to
public static void main(String[] args) {
User odaSensei = new User();
odaSensei.name = "Oda-Sensei";
User michaelBay = new User();
michaelBay.name = "Michael Bay";
Book firstBook = new Book("One Piece", odaSensei, 100, 123456);
Book secondBook = new Book("Life of Megan Fox", michaelBay, 200, 928765);
}
Be sure to set the other variables of the authors The other option is to change the type of authors to String, in which case the main method will not have the change.
I'd also recommend adding a constructor for Users, so that you can just initialize all of the variables from the new call.
The second part "Separately, create another user and call the readBook method on that user, passing in one of the created books"
Is telling you to create a brand new user, e.g. bob
User bobUser = new User();
bobUser.name="Bob";
and then take this new user and have him read one of the books:
bobUser.readBook(firstBook);
The goal is to get the read book to print out:
Bob read One Piece
To do this, you'll need to change the readBook method from:
public void readBook(Book book) {
System.out.println(name + " read " + title.title);
}
to:
public void readBook(Book book) {
System.out.println(name + " read " + book.title);
}
I am making a simple program that sets the title and name of an object: book1. Eventually, the goal is to have several books under the Patron class that will use the Book class to assign values. However, I am running into difficulty simply getting the Patron class to acknowledge the Book class methods.
Basic Tester/Main method:
import java.util.Scanner;
public class ProjectFiveSix {
public static void main(String[] args) {
String title = "Bob";
String name = "Hugo"; // name of patron (class assigning book)
String author = "Rodrigo";
Patron patronOne = new Patron();
patronOne.setName(name);
Patron Class :
public class Patron {
private String name;
private Book book1;
private Book book2;
private Book book3;
public Patron(){
name = "";
book1 = null;
book2 = null;
book3 = null;
}
public String setName(String name){
return name;
}
public String borrowBook(String book1, String titleFinal, String authorFinal, String title, String author){
if (book1 == null){
book1.setTitle(titleFinal); //**
book1.setAuthor(authorFinal); //***
}
}
}
Book Class:
public class Book {
private String titleFinal;
private String authorFinal;
public Book(){
titleFinal = "";
authorFinal = "";
}
public String setTitle(String title){
titleFinal = title;
return titleFinal;
}
public String setAuthor(String author){
authorFinal = author;
return authorFinal;
}
}
Here I am getting "Cannot find Symbol" on both lines book1.settitle and book1.setauthor. The book has been instantiated and I cannot figure out the problem.
Thanks in advance!
You declared your parameter book1 (a String) as the same name as your instance variable book1 (a Book). To reference the instance variable, either name the parameter a different variable name, or use this. to specify the instance variable:
this.book1.setTitle(titleFinal); //**
this.book1.setAuthor(authorFinal); //***
Either way, you'll need to create an actual Book instance, or else your instance variable book1 will remain null and you'll get a NullPointerException.