Updating a hashmap within a hashmap with a class - java

Sorry about the title really struggling to name this. Lets see how the question goes.....
In java I have a class called book which contains the following code. Where name is the book name, the hashMap string is the critics name and the hashMap Integer is the critic score.
public class book {
private String name;
private HashMap<String, Integer> results = new HashMap<String, Integer>();
}
I then have another class called bookRecord which contains the following code.
private HashMap<Integer, Book> bookRecord = new HashMap<Integer, Book>();
I have written a UI that allows me to enter a new book and save that book into the bookRecord.
The Integer in bookRecord is an ID for the book.
I have written a query to search by the ID and return the name of the book. Now I want to be able to update the book if a new critic and score is available.
I have been playing with a for each loop to find the right key in the book record and then if the key is found another for each loop but I have confused myself.
Any advice?

You have two options:
First option you make the results HashMap public and can achieve something like this:
Book uBook = records.get(BOOK_ID_YOU_WANT_TO_UPDATE);
if (uBook != null) {
uBook.results.put("New critic name", Critic_SCORE);
}
Seconds option is to leave the results private but add a new method addCriticScore(String criticName, Integer score):
// In your class that updates the book
Book uBook = records.get(BOOK_ID_YOU_WANT_TO_UPDATE);
// In the Book class
public void addCriticScore(String criticName, Integer score) {
this.results.put(criticName, score);
}
P.S: Don't forget to rename your class book to Book. In java the class name is with capitals

Related

Checking if a user defined item exists in a HashSet

Im making a class called Book which contains the books name and price. If i insert those data into a HashSet, how would be i able to check if a book exists in that HashSet by only searching for the book name?
I currently have:
public Book(String name, double price){
this.name = name;
this.price = price;
}
public static void main(String[] args){
HashSet<Book> hs = new HashSet<Book>();
Book book1 = new Book("Plant Book", 19.99);
Book book2 = new Book("Garden Book", 24.99);
Book book3 = new Book("Cook Book", 14.99);
hs.add(book1);
hs.add(book2);
hs.add(book3);
System.out.println(hs.contains("Plant Book")); //I want this to return true
}
So how would i be able to search for Plant Book in this HashSet?
Using a stream can make life quite easy sometimes:
hs.stream().anyMatch(book -> "Plant book".equals(book.getName()));
Definitely recommend implementing equals and hashCode for the class that will be added to the HashSet since that will solve the use case of not allowing "similar" items to be added to the HashSet.
For your requirements, iterating over the items and checking for the name is likely the best thing to do.
As was mentioned in the comments by Thomas, it seems a map would better suit your requirements. Here I am using a record to demonstrate.
Everything is pretty much the same except for the methods used for accessing and testing a map.
record Book(String getName, double getPrice){}
Map<String, Book> hmap = new HashMap<>();
Book book1 = new Book("Plant Book", 19.99);
Book book2 = new Book("Garden Book", 24.99);
Book book3 = new Book("Cook Book", 14.99);
// using put to enter the name and Book instance
hmap.put(book1.getName(),book1);
hmap.put(book2.getName(),book2);
hmap.put(book3.getName(),book3);
// here using containsKey for the check
String name = "Plant Book";
if (hmap.containsKey(name)) {
System.out.println(hmap.get(name));
}
prints
Book[getName=Plant Book, getPrice=19.99]
You can also put the keys in lowercase or uppercase names and then just use the required case names for checking and retrieval.
hmap.put(book.getName().toLowerCase(), book);

Java streams - getting a map from list of maps

I have a class University that contains (among other things) a list of semesters and a method:
public Map<String,Integer> gradesMap(Student s,Semester s)
that should return a map of grades for a given student in a given semester.
Classes Semester and Course look something like this:
public class Semester{
...
private List<Course> courses;
public List<Courses> getCourses(){return courses;}
...
}
public class Course{
...
String courseName;
private Map<Student,Integer> courseGrades;
public Map<Student,Integer> getCourseGrades(){return courseGrades;}
public String getCourseName(){return courseName;}
...
}
I tried writing something like:
Map<String,Integer> grades=semester.getCourses().stream().
forEach(c->c.getCourseGrades()).collect(Collectors.toMap(key,value));
but I'm not sure how to fetch the key and value for my map. Any suggestions would be appreciated.
Edit: Output map should contain a Course name and a grade.
You can get the course grade from the Course Grade map by the student and collect grade as the map's value and course name as the key.
Map<String,Integer> gradesMap =
semester.getCourses()
.stream()
.collect(Collectors.toMap(c -> c.getName(),
c -> c.getCourseGrades().get(studentObj)));
Note: Make sure you defined equals() and hashCode() for Student

Best way to implement this record (store date along with ID and quantity)?

Im wondering the best way of storing the following information:
I have an Account Object, within each account object I need to keep track of date, items purchased on that date, and the number of items . This is in addition to many other things such as client ID for the account. Im about to implement this in the following way
class Account{
int clientID;
LinkedHashMap<String(the date), Map<int(itemID), int(quantity)>> = new ...
...
}
I was wondering if anyone has any time before I go ahead and implement this? I mean other thing I thought of was an inner class such as
Class Account{
class Item{
String Date
Array<Int> itemID
Array<Int> item quantity
}
But I feel the first way wold be better. THanks for your suggestions.
P.S I know there's issues in the code like the brackets in the hashmap this is just to help you see what I'm getting at :)
I think this could be good design:
public class Acount {
private int clientId;
private List<Purchase> purchases;
}
public class Purchase {
private Date date;
private Map<Item, Integer> itemsCount;
}
public class Item {
private int itemId;
}
An Account has a clientId and a list of purchases.
Each Purchase has a date and a map that identifies the purchased Items and the quantity of each one.
Best way to store id and data
HashMap<String, String> multiMap = new HashMap<String,String>();
// Put elements to the hashMap
hashMap.put("id1", "data1");
hashMap.put("id2", "data2"); hashMap.put("id3", "data3");

Replacing ArrayLists with HashMaps

I am currently working on a project where I am replacing the ArrayLists in my code with HashMaps and I've run into a problem. In this section of my code I am creating a new "Book" from my book class and in the "get book" section is where I am having the problem. I am trying to check the (now)HashMap books to see if the book ID from the getId() method match the bookID of the book object. How Should I go about Iterating over my HashMap with the Book object?
This is my HashMap: HashMap<String, String> books = new HashMap<String, String>();
if (users.containsValue(new User(userID, null, 0))
&& books.containsValue(new Book(bookID, null))) {
// get the real user and book
Book b = null;
User u = null;
// get book
for (Book book : books) {
if (book.getId().equalsIgnoreCase(bookID)) {
b = book;
break;
}
}
You probably needs something like this. I've used names instead of ID's, but I hope you get the drift...
// setting up the test
HashMap<String, String> borrowers = new HashMap<String, String>();
borrowers.put("Lord of the Rings", "owlstead");
borrowers.put("The Hobbit", "sven");
borrowers.put("Vacuum Flowers", "owlstead");
// find out what I borrowed from the library
String userID = "owlstead";
List<String> booksBorrowed = new ArrayList<>();
// iterating through the books may not be very efficient!
for (String bookName : borrowers.keySet()) {
if (borrowers.get(bookName).equals(userID)) {
booksBorrowed.add(bookName);
}
}
// print instead of a return statement
System.out.println(booksBorrowed);
There are only Strings in your Hashmap.
No Books.
As there are no Books in the HashMap, you will never be able to get a Book object out of it.
If you want to identify Book objects with String objects, a HashMap works, but you have to set it up in this way:
HashMap<String, Book> books = new HashMap<String, Book>();
Here's a full working example of how a Hashmap could be used with Book objects:
import java.util.HashMap;
public class Book
{
private String title;
private int pages;
public Book(String title, int pages)
{
this.title = title;
this.pages = pages;
}
public String toString()
{
return title + ", " + pages + "p.";
}
public static void main(String[] args)
{
//creating some Book objects
Book theGreatBook = new Book("The great Book of awesomeness", 219);
Book klingonDictionary = new Book("Klingon - English, English - Klingon", 12);
//the Map:
HashMap<String, Book> library = new HashMap<String, Book>();
//add the books to the library:
library.put("ISBN 1", theGreatBook);
library.put("ISBN 2", klingonDictionary);
//retrieve a book by its ID:
System.out.println(library.get("ISBN 2"));
}
}
Why do you use Strings to identify objects?
The Strings are not unique, so if two books have the same ID, you will run into problems.
I would add the ID of an object as a data field to the object itself.
Making the association of an ID to an object in a HashMap works, but is very lose.
Without the map, the association is gone.
It's also prone to error, as typos in your Strings cannot be cached by the compiler.
Maybe you run into a NullPointerException at runtime.
Especially because also your User class has such an "ID" I am wondering if you add this to every class and would like to say that there really is no need to do this (unless you have other reasons).
To identify an object, simply use the reference to the object.
If you have a typo in one of your variable names that reference an object, the compiler will be able to tell you so.

Using ArrayList to store variables

I'm coding a project to store an array of objects, probably in an arraylist.
So, my object has data elements, getters and setters. I do not have an idea how to access the elements of the object.
For example my object is a book which has the following data elements.
Book
->Author
->Price
->Date
If the price of a certain book changes, how do I update the arrayList? Do I need a 2d arrayList? I think indexOf would not work because it is an object? Not really sure.
I'm just a newbie in programming, so I'm not sure if arrayList is the right data structure to use. Thank you very much for reading this, your help will be appreciated.
You can access an object in an ArrayList by it's index. Say you want the third book:
List<Book> lisOfBooks = someFunctionWhichGetsListOfBooks();
Book book = listOfBooks.get(2);
(Remember indexes start at 0 in java) Then you can do:
String Author = book.getAuthor();
or to set the price:
book.setPrice(newPrice);
If you do not know where in the list the particular book is you have 2 choices: 1) iterate through the list until you find the book you want or 2) you can use a HashMap. But you need to decide what to key the book on (what makes each book unique?). Let's say you'll be looking up books by id. Then you can put all your books in a HashMap keyed by an Integer id:
HashMap<Integer, Book> bookHash = new HashMap<Integer, Book>();
for (Book book : listOfBooks) {
bookHash.put(book.getId(), book);
}
Then to retrieve any book you can do:
Book book = bookHash.get(bookId);
Obviously this assumes your Book class has appropriate getter and setter methods. E.g:
public class Book {
private int id;
private String author;
...
public String getAuthor() {
return author;
}
public void setPrice(price) {
this.price = price;
}
...
}
An ArrayList is a good implementation if you need to store your objects in a list. A good alternative for a collection of books: a Map implementation. This is useful if every book can be identified by a unique key (name, ISBN number, ...) and you use that key to "get" a book from the collection.
A book is an object on its on and should be modeled with a Book class. So if you want to store books in list structure, this would be OK:
List<Book> books = new ArrayList<Book>();
books.add(new Book("Robert C. Martin","Clean Code"));
books.add(new Book("Joshua Bloch","Effective Java"));
For a map, a code fragment could look like this:
Map<String, Book> books = new HashMap<String, Book>();
books.put("978-0132350884", new Book("Robert C. Martin","Clean Code"));
books.put("978-0321356680", new Book("Joshua Bloch","Effective Java"));
Edit - finding a book and updating the price
With a list, you have to iterate through the list until you find the object that represents the book you're looking for. It's easier with the map shown above, if you always can use the ISBN, for example. With the list, it goes like this:
List<Book> books = getBooks(); // get the books from somewhere
for (Book book:books) {
if (matchesSearchCriteria(book)) { // some method to identify a book, placeholder!
book.setPrice(newPrice); // modify the books price
break;
}
}
You need to create a custom "datatype", basically a POJO (Plain old java object) that will have fields for all the parameters you want. Let's call it Book:
class Book {
public String author;
public double price;
public Date date;
}
Of course it's better to have private fields and encapsulate with getters and setters, i jsut wrote that for simplicity.
Then you can create a List of Book objects.
List<Book> books = new ArrayList<Book>();
And add Books to it which you can then later iterate through like this:
for (Book book : books) {
System.out.println(book.getAuthor());
}
I'd be looking at some sort of lookup data structure like a hashmap, for example
HashMap<String, Hashmap<String,String>> books = new Hashmap<String, HashMap<String, String>>();
HashMap<String, String> bookelements = new HashMap<String,String>();
bookelements.put("Author","J.K Rowling");
bookelements.put("Price","£5");
bookelements.put("Year","2000");
books.put("harry potter",bookelements);
//Get elements like so
String author = (String)books.get("harry potter").get("Author");

Categories