Method to count the number of books of an author - java

So I need to create 3 classes "Book"(with fields author, title and body, as string), "Shelf"(with fields id (string) and books (array) and "Library". Then I shall create a method "countAuthor".which counts (and returns as an int) the number of books in the library written by an author whose name (String) is passed as an argument to the method:
class Book {
private String author;
public String getAuthor() {return author;}
private String title;
public String getTitle() {return title;}
private String body;
public String getBody() {return body;}
}
class Shelf {
private String id;
public String getId() {return id;}
private int[] books;
public int[] getBooks() {return books;}
}
class Library {
private int[] shelves;
public int[] getShelves() {return shelves;}
public int countAuthor(String authorName) { // returns the number of books in the library written by author whose name (String)
//is passed as an argument to the method.
int a = ;
return a; // a is the number of books of the author
}
}
After all, in the class (where the main method is stated), I need to add the necessary code and the program overall shall print the number of books an author has written. This is the class of the main method:
public class Exercise {
public static void main(String[] args) {
Shelf shelf1 = new Shelf("Shelf1",
new Book[] {
new Book("Babel", "Odessa Tales", "babelode"),
new Book("Joyce", "Ulisses", "joyceuli")
});
Shelf shelf2 = new Shelf("Shelf2",
new Book[] {
new Book("Mann", "Dr Faustus", "mannfau"),
new Book("Babel", "Red Cavalry", "babelred")
});
Library lib = new Library(
new Shelf[] { shelf1, shelf2 });
System.out.println("# of books by this author: " + lib.countAuthor("Babel"));
}
}
Which should print # of book by this author: 2
Where I am confused with is what to add to the countAuthor() method. And if I need anything in addition to the method. I am pretty new to Java so I still get confused with some structures, especially with the loops.

Here it is. In your code you are missing constructors that you are trying to use so I added them. The logic of counting the books is just go through all the shelves in the lib and count all the books on these shelves with the author name.
public class Exercise {
public static void main(String[] args) {
Shelf shelf1 = new Shelf("Shelf1", new Book[]{
new Book("Babel", "Odessa Tales", "babelode"),
new Book("Joyce", "Ulisses", "joyceuli")});
Shelf shelf2 = new Shelf("Shelf2",
new Book[]{
new Book("Mann", "Dr Faustus", "mannfau"),
new Book("Babel", "Red Cavalry", "babelred")
});
Library lib = new Library(new Shelf[]{shelf1, shelf2});
System.out.println("# of books by this author: " + lib.countAuthor("Babel"));
}
}
class Book {
public Book(String author, String title, String body) {
this.author = author;
this.title = title;
this.body = body;
}
private String author;
public String getAuthor() {
return author;
}
private String title;
public String getTitle() {
return title;
}
private String body;
public String getBody() {
return body;
}
}
class Shelf {
public Shelf(String id, Book[] books) {
this.id = id;
this.books = books;
}
private String id;
public String getId() {
return id;
}
private Book[] books;
public Book[] getBooks() {
return books;
}
}
class Library {
public Library(Shelf[] shelves) {
this.shelves = shelves;
}
private Shelf[] shelves;
public Shelf[] getShelves() {
return shelves;
}
public int countAuthor(
String authorName) { // returns the number of books in the library written by author whose name (String)
//is passed as an argument to the method.
int count = 0;
for (Shelf shelf : shelves) {
for (Book book : shelf.getBooks()) {
if (book.getAuthor().equals(authorName)) {
count++;
}
}
}
return count; // a is the number of books of the author
}
}
Output:
# of books by this author: 2

As I can see from your question, the structure will be like this.
Library can have many Shelf and in every Shelf there are many books.
So to count the no of books for a particular author, first you need all the books.
It will be something like this.
public int countAuthor(String author) {
int result = 0;
for(Shelf shelf : shelves) {
for(Book book : shelf.getBooks()) {
if(author.equals(book.getAuthor()) {
result++;
}
}
}
return result;
}

Related

How do I match parts (title or isbn) from my book array that was created from a text file?

When I run this code, it gives an error saying cannot involve get__() on the array type Book[].. In the main method, I have a book array with the information from a text file -- title, isbn, price, qty, forsale.
public static int searchByTitleOrISBN(Book[] b)
{
int i = 0;
// print a message "Enter the Title or ISBN of the book: "
System.out.println("Enter the Title or ISBN of the book: ");
String input = scan.next();
// use a while loop to search through the array books using a counter and as long as no match is found
while (i < b.length) {
// if there's a match for the title or a match for the isbn and the book quantity > 0 and the book is for sale
if ((b.getTitle().equals(title) || b.getISBN().equals(isbn)) & b.getQty() > 0 && b.isForSale()) {
Basically what you want is to search the entire list.If you want to keep up your present implementation, then the solution given by #Jens works.
But If you go by searching one by one it would be O(n) but if you leverage inbuilt HashMaps you can do it with O(1) using hashCode and equals and no need of looping through all the objects for each and every search.
the Book class which keeps the data of the book. hashCode and equals is implemented here.
public final class Book{
private final String title;
private final String isbn;
private double price;
private int quantity;
private boolean forSale;
public final Key key;
public Book(String title, String isbn, double price, int quantity,boolean forSale){
this.title = title;
this.isbn = isbn;
this.price = price;
this.quantity =quantity;
this.forSale = forSale;
this.key = makeKey(title,isbn);
}
private static Key makeKey(String title,String isbn) {
return new Key(title,isbn);
}
public Key getKey() {
return this.key;
}
public String getTitle(){
return this.title;
}
public String getISBN(){
return this.isbn;
}
#Override
public final String toString(){
String s = this.title +"; "+ this.isbn+ "; "+this.price+"; "+this.quantity;
return s;
}
public static final class Key{
private final String title;
private final String isbn;
private Key(String title,String isbn) {
this.title = title;
this.isbn = isbn;
}
private String getTitle() {
return this.title;
}
private String getISBN() {
return this.isbn;
}
//calculates the hash of the entry, if we don't override this it will
//use the hash of the reference. so we need to change it for comparision
#Override
public final int hashCode(){
return this.title.hashCode()+this.isbn.hashCode();
}
//if two components have same hash code, then we can use extra criterion
//to check if the two objects are same. in the book case the hash is
//unique.since we are using the title and the isbn;
#Override
public final boolean equals(Object obj){
if(this==obj){
return true;
}
if(obj!=null && this.getClass()==obj.getClass()){
Key tempObj = (Key)obj;
return (this.title == tempObj.getTitle()) && (this.isbn == tempObj.getISBN());
}
return false;
}
}
}
BookMap class which stores all the book objects in form of Map<Book.Key,Book>. This will help with the easy retrival of book data.
public final class BookMap{
private final Map<Book.Key,Book> map;
private final String name;
public BookMap(String name){
this.name = name;
this.map = new HashMap<>();
}
public final String getName(){
return this.name;
}
public final Map<Book.Key,Book> getMap(){
return Collections.unmodifiableMap(this.map);
}
public final void addBook(Book book){
this.map.put(book.getKey(),book);
}
public final Book getBook(Book book){
Book.Key tempKey = book.getKey();
return this.map.get(tempKey);
}
public final boolean findBook(Book book){
if(book != null) {
return this.map.containsKey(book.getKey());
}
return false;
}
#Override
public final String toString() {
String s ="Books list : \n";
for(Map.Entry<Book.Key,Book> b:this.map.entrySet()) {
s= s+b.getValue()+"\n";
}
return s;
}
}
Now a sample Main.js with static main method to retrieve the book list.
public class Main {
public static BookMap list = new BookSet("General list");
public static void main(String[] args) {
Book temp = new Book("Journey to the center of the earth","isbn-001-002-0455",9.99,15,false);
list.addBook(temp);
temp = new Book("The Time Machine","isbn-001-002-0456",9.99,15,false);
list.addBook(temp);
temp = new Book("The War of the Worlds","isbn-001-002-0457",8.99,15,false);
list.addBook(temp);
temp = new Book("Brave New World","isbn-001-002-0458",11.99,15,false);
list.addBook(temp);
temp = new Book("Ninteen Eighty-four","isbn-001-002-0459",19.99,15,false);
list.addBook(temp);
temp = new Book("Ray Bradbury","isbn-001-002-0460",14.99,15,false);
list.addBook(temp);
temp = new Book("I, Robot","isbn-001-002-0461",12.99,15,false);
list.addBook(temp);
temp = new Book("Foundation","isbn-001-002-0462",12.99,15,false);
list.addBook(temp);
temp = new Book("The Martial Chronicles","isbn-001-002-0463",3.99,15,false);
list.addBook(temp);
temp = new Book("Fahrenheit 451","isbn-001-002-0464",6.99,15,false);
list.addBook(temp);
//testing with the book already in the list;
temp = new Book("Fahrenheit 451","isbn-001-002-0464",0,0,false);
//prints book detail
System.out.println(list.getBook(temp));
//testing with the book already in the list;
temp = new Book("I am not in the list","isbn-001-002-0464",0,0,false);
//prints null as the book is not in the list
System.out.println(list.getBook(temp));
System.out.println(list);
}
}
The above is a rough idea, you can develop more on it, i have used final for classes in order to prevent subclassing, as it would become complex with inheritence to understand and debug.i like avoiding complexity as much as i can. If some common pattern is there, then i will try to use abstract classes.
You have to acces an element in your loop not the array itself:
while (i < b.length) {
// if there's a match for the title or a match for the isbn and the book quantity > 0 and the book is for sale
if ((b[i].getTitle().equals(title) || b[i].getISBN().equals(isbn)) & b[i].getQty() > 0 && b[i].isForSale()) {

How to create a better object

Related to my previous thread, i want to print an output like this:
bookId = "1234" (String)
bookName = "Machine Learning" (String)
price = $20 (int)
ratings = (array of object)
rater = a, score = 5
rater = b, score = 3
But this time, i tried to use an OOP manner.
So first, i made a POJO class called ProductView, the class will be look like this:
public class ProductView {
// field
private String bookId;
private String bookName;
private int price;
private List<Ratings> ratings;
// a constructor i tried to make
public ProductView(String bookId, String bookName, int price, List<Ratings> ratings) {
this.bookId = bookId;
this.bookName = bookName;
this.price = price;
this.ratings = ratings;
}
public String getBookId() {
return bookId;
}
public void setBookId(String bookId) {
this.itemId = itemId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Ratings getRatings() {
return ratings;
}
public void setRatings(Ratings ratings) {
this.ratings = ratings;
}
}
After that, i made a class called Ratings with the following field:
public class Ratings {
private String rater;
private int score;
public Ratings(String rater, int score) {
this.rater = rater;
this.score = score;
}
}
And finally, i made a Main Class called Main:
public class Main {
public static void main(String[] args) {
}
}
In the Main Class, i want to create an instance of the ProductView class and give it some value.
But i don't know how to do it with a list object param in my constructor.
Anyone can give me some insight?
first:
List is an interface, you should pass an implementation of list such as ArrayList or similar
second:
you have a compilation error in ProductView -> SetBookId, in this.itemId you don't have itemId as member or constructor parameter
furthermore, in get/set rating you need to pass and return list of Ratings.
nameing:
Ratings is actually just a Rating, you can make a new class of List or just use the Rating as is but change the name
now for your Question:
you can initialize first the list with objects and then send it to the constructor
such as:
List<Ratings> ratings = new ArrayList<>();
ratings.add(new Ratings("rater",5));
ratings.add(new Ratings("rater2",6));
ProductView productView = new ProductView("bookId","bookName",1,ratings);
Or, just initialize the ArrayList in the Constructor, the first way is preferable:
ProductView productView1 = new ProductView("bookId","bookName",1,
new ArrayList<Ratings>(Arrays.asList(new Ratings("rater",5), new Ratings("rater2",6))
));
hopefully, this answers your question
same as DodgyCodeException mentioned in the comments.

ArrayList book class

Creating a Book class, below are what the methods do. I'm currently stuck on how to add methods regarding removing author by name and email. I can't upload the UML image as I'm new and dont have enough rep points.
Create a new instance of the authors ArrayList inside the constructors.
Implement a method addAuthor(Author author) to add the given Author instance to this Book.
Implement a public method removeAuthorByName(String name) that uses the given String to search the authors ArrayList. If it finds an Author object with a name matching the given String it passes the reference to this object to a private method removeAuthor(Author author).
Implement a public method removeAuthorByEmail(String email) that uses the given String to search the authors ArrayList. If it finds an Author object with an email matching the given String it passes the reference to this object to a private method removeAuthor(Author author).
Implement a private method removeAuthor(Author author) which when given a reference to an Author object removes the reference to that object from the authors ArrayList.
The toString() method shall return "book-name by n authors", where n is the number of authors.
The printAuthors() method shall print the names of all the authors from an Arraylist.
My code :
class Book {
private String name;
private double price;
// private Author[] authors = new Author[5];
//priavte authors =new ArrayList<Author>();
private Map authors = new HashMap<String, Author>();
// private ArrayList<Author> authors = new ArrayList<Author>();
private int qtyInStock = 0;
public Book(String name, double price) {
this.name = name;
this.price = price;
}
public Book(String name, double price, int qtyInStock) {
this.name = name;
this.price = price;
this.qtyInStock = qtyInStock;
}
public String getName() {
return this.name;
}
public double getPrice() {
return this.price;
}
public Collection<Author> getAuthors() {
return authors.values();
}
public void setPrice(double price) {
this.price = price;
}
public int getQtyInStock() {
return this.qtyInStock;
}
public void setQtyInStock(int qtyInStock) {
this.qtyInStock = qtyInStock;
}
public void printAuthors() {
authors.values().forEach(System.out::println);
}
public void addAuthor(Author author)
{
authors.put(author.getName(name), author);
}
public void removeAuthorByName(String name) {
authors.remove(authors.get(name));
}
public void removeAuthorByEmail(String email){
authors.remove(authors.get(email));
}
public void removeAuthor(String author){
authors.remove(authors.get(author));
}
public String toString() {
return "'" + name +"' by " + authors + " authors";
}
}
test cases
Author a = new Author("Adam", "adam#gmail.com", 'm');
Author b = new Author("Ben", "ben#gmail.com", 'm');
Author c = new Author("Calvin", "calvin#gmail.com", 'm');
Author d = new Author("Danielle", "Danielle#gmail.com", 'f');
Book book1 = new Book("The House", 70.00, 5);
book1.addAuthor(a);
book1.addAuthor(b);
book1.addAuthor(c);
book1.addAuthor(d);
book1.removeAuthorByName("Ben");
System.out.println(book1);
book1.printAuthors();
output:
The House by 3 authors
Adam
Calvin
Danielle
Added the UML on this link : https://gyazo.com/4afc1bafa03210044fafe06650859cb0
I suggest to change the arraylist to HashMap.
private ArrayList<Author> authors = new ArrayList<Author>();
to
private Map authors = new HashMap<String, Author>();
Change below methods-
public Collection<Author> getAuthors() {
return authors.values();
}
public void printAuthors() {
authors.values().forEach(System.out::println);
}
public void addAuthor(Author author)
{
authors.put(author.getName(), author);
}
public void removeAuthorByName(String authorName) {
authors.remove(authors.get(authorName));
}

How do I add more than one return statement inside a method?

I am trying to return some values of some objects by using getter and setter method. Now I can't return more than one value inside a single method. In this case, do I need to create different methods for each return. If not, how could I solve it?
My code:
package books;
public class BooksObject {
//variable for book 1
String name1 = "The brief history of time";
String isbn1 = "111";
String[] authName1 = {"S. Hawking", " Hawking's friend"};
//variable for book 2
String name2 = "100 years of solitude";
String isbn2 = "222";
String[] authName2 = {"G. Marquez", "Marquezs friend"};
//All setters
public void setBook1(String n_1, String i_1, String[] a_N1) {
name1 = n_1;
isbn1 = i_1;
String[] authName1 = a_N1;
}
public void setBook2(String n_2, String i_2, String[] a_N2) {
name2 = n_2;
isbn2 = i_2;
String[] authName2 = a_N2;
}
//All getters method
public String getBook1() {
return name1;
//return isbn1; //shows error
//return String[]authName1;//Shows error
}
}
[Note: Of course I am going to call all these method in my main class. I just haven't posted it here.]
You should create a Book class that contains the 3 properties, and your getter would return a Book instance.
Instead of
String name1 = "The brief history of time";
String isbn1 = "111";
String[] authName1 = {"S. Hawking", " Hawking's friend"};
You'll have
Book book1 = new Book ("The brief history of time", "111", {"S. Hawking", " Hawking's friend"});
Then :
public Book getBook1() {
return book1;
}
You can further improve your BooksObject by having a books array (Book[]) instead of a different variable for each Book. Then you wouldn't need a separate getBooki method for each book.
I think you shoul change your code as shown below:
public class Book
{
private String name;
private String isbn;
private String[] authors;
/* constructor */
public Book(String name, String isbn, String[] authors) {
this.name = name;
this.isbn = isbn;
this.authors = authors;
}
/* setter */
public void setName(String name) {
this.name = name;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public void setAuthors(String[] authors) {
this.authors = authors;
}
/* getter */
public String getName() {
return name;
}
public String getIsbn() {
return isbn;
}
public String[] getAuthors() {
return authors;
}
}
public class Main
{
public static void main(String[] args) {
Book book1 = new Book(
"The brief history of time",
"111",
new String[]{"S. Hawking", " Hawking's friend"}
);
Book book2 = new Book(
"100 years of solitude",
"222",
new String[]{"G. Marquez", "Marquezs friend"}
);
}
}

trying to print a method from arraylist

I am trying to print title from my member class using array in my library class
public class Book gives me this error :
http://screencast.com/t/tqpJp2BF8sH
{
// instance variables - replace the example below with your own
private int x;
private Integer bookid;
private String author;
private String title;
private String ficornonfic;
/**
* Constructor for objects of class Book
*/
public Book(Integer bookID, String Author, String Title, String FictionORnonfiction )
{
bookid = bookID;
author = Author;
title = Title ;
ficornonfic = FictionORnonfiction;
x = 0;
}
public String PrintListOfBooks()
{
return title;
}
public String toString() {
return "Title:" + title + " BookId: " + bookid + " Author: " + author + ".";
}
public int getTitle() {
return this.title;
}
}
---------------------------------------------------------
this is my library class
import java.util.ArrayList;
public class Library
{
private ArrayList<Member>listOfMembers;
public Library()
{
listOfMembers = new ArrayList<Member>();
listOfBooks = new ArrayList<Book>();
}
public void storeMember(Member Member)
{
listOfMembers.add(Member);
}
public int numberOfMembers()
{
return listOfMembers.size();
}
public void listMembers()
{
for (int item=0; item<listOfMembers.size(); item++ ) {
Member m = listOfMembers.get (item);
System.out.println(m.GetWholeName());
}
}
public Member findMember(int id) {
for(Member member : listOfMembers) {
if (member.getId() == id) {
return member;
}
}
return null;
}
private ArrayList<Book>listOfBooks;
public void storeBook(Book Book)
{
listOfBooks.add(Book);
}
public int numberOfBooks()
{
return listOfBooks.size();
}
public void listBooks()
{
for (int item=0; item<listOfBooks.size(); item++ ) {
Book b = listOfBooks.get (item);
System.out.println(b.PrintListOfBooks());
}
}
public Book findBook(string title) {
for(Book book : listOfBooks) {
if (book.getId() == id) {
return book;
}
}
return null;
}
}
I am trying to print title from my member class using array in my library class
public class Book gives me this error :
http://screencast.com/t/tqpJp2BF8sH
The title is a String, not an int. You can change the method signature to match the field type:
public String getTitle() {
return this.title;
}
First, as others have noted your title is a String not an int. So change the return type of getTitle() (or remove it altogether). Because it appears like you've correctly overridden toString() in Book to get all the information, and you could iterate the contents of your List with a for-each loop. Something like,
for (Book b : listOfBooks) {
System.out.println(b);
}
which is equivalent to
for (int i = 0; i < listOfBooks.size(); i++) {
Book b = listOfBooks.get(i);
System.out.println(b.toString());
}
Finally in Java, by convention, method names start with a lower case letter.
You are essentially telling the program to return an Integer when the value you wish to return is a String.
If you change int to String, the error will go away.
public String getTitle() {
return this.title;
}

Categories

Resources