Prevent duplicated ID entry in Java - java

I have a set up a constructor in a Book class, and another class I have set up an ArrayList of type Book. The book expects to receive a title, author, bookID, copies, timesLoaned, onLoan.
I am looking to find the most efficient way to ensure that there are no duplicated bookID before adding a book. I have not learned about Map etc, so would like to avoid this for now. I was thinking about the use of a for loop to check the bookID's before adding.
Below is my addBook method:
// Adding a book to ArrayList
public void addBook(){
System.out.println("==============================");
// Getting user input and assigns it to variables
System.out.print("Enter a title: ");
String title = sc.nextLine();
System.out.print("Enter an author: ");
String author = sc.nextLine();
System.out.print("Enter quantity of books: ");
int quantity = checkInput(sc); // checks for valid integer
// Generates random ID for book
int bookID = (int) Math.round(Math.random() * 1000000);
// Adding book the the ArrayList, using user input taken above
newBook.add(new Book(title, author, bookID, quantity, 0, false));
// Adding to maxReturns for returnBook()
maxReturns.add(quantity);
// Testing that it has added - TAKE OUT AFTER COMPLETION
for(int i = 0; i < newBook.size(); i++){
System.out.println(newBook.get(i).getBookID() + " " + newBook.get(i).getTitle());
}
// Showing its been added
System.out.println("Book has been added!");
System.out.println("==============================");
}

I would also suggest a Map, but if you want to use an ArrayList you should think that ArrayList implements the List interface, which has a contains method. You could thus just query whether your ArrayList contains the new book. The contains method will then loop through the ArrayList using the equals method to check whether each book is equal to the new one you want to compare against. It would be a good idea to (correctly) override your Book's HashCode in a safe way.

Related

How do I Display results that match the users input from a JOptionPane in linked list?

I have created an object of Type Car with make, model, year, mileage as variables,
The program reads from a file through and the displays through linked lists a sorted and an unsorted version. I have created a class to add values to the object. How should I modify the code so that when the users enter an input let say Ford, the GUI displays only the values of Cars named Ford? that has a and object named
Here is a link to what the GUI displays I want to display in the sorted list only values of the same input as the user entered.
String menuName = event.getActionCommand();`
String input;
// if clicked "Add," prompt user for input dialog
// and if valid RN, add it to each list,
// then display the list to reflect the addition
if (menuName.equals("Add")) {
input = JOptionPane.showInputDialog(null, "Enter a Car to add:");
try {
StringTokenizer st = new StringTokenizer(input);
Car cr = new Car(st.nextToken(), st.nextToken(), Integer.parseInt(st.nextToken()),
Integer.parseInt(st.nextToken()));
crGUI.inOrder.add(cr);
crGUI.sorted.add(cr);
} catch (IllegalArgumentException iae) {
JOptionPane.showMessageDialog(null, "Illegal Car: " + input);
System.out.println("Illegal Car: " + input);
}
crGUI.displaySorted();
crGUI.displayUnsorted();
} } }
if crGui.displaySorted() can check what type of make it is. If you pass it some sort of string maybe?
The best way for your requirement could be using hashmaps with 'make' as a key and a list of objects as value.
Hashmap<string,List<Car>> carGui = new Hashmap<string,List<Car>>();
With the code provided, i could not understand the whole scope of carGui. May be this can give you an idea.

setters/getters and getName() and application error [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
My customer.dat files looks like as follows:
4
Jon 1000
Jane 2000
Jake 20000
Drake 100000
The first number represents the total number of customers in that file, while the first string is the Name of the customer and the latter is the balance they have.
The following code is the application code I have written. I want it to read from the customer.dat and create an array. The problem with the application is that I created a customer ID, which checks the name the user inputs(if it exists in the array( and then sets a customer ID. However, whenever I run the application, no matter what name I type, even if I type Drake - and type "1" to view the portfolio, it ends up always showing the first name which is Jon.
Scanner infile2 = new Scanner(new File("customer.dat"));
customer[]mycustomers; // declaring an array to stock
int numofcustomers = infile2.nextInt();
mycustomers = new customer [numofcustomers];
for (int i = 0; i < numofcustomers; i++)
{
mycustomers[i] = new customer(infile2.next(),infile2.nextDouble(), numofcustomers);
System.out.println(mycustomers[i].toString());
}
Scanner input = new Scanner (System.in);
System.out.println("Please type in your name");
String Name = input.nextLine();
int cusID = 0;
for (int i = 0; i < numofcustomers; i++)
{
if ( Name == mycustomers[i].getName())
{
cusID = i;
}
}
System.out.println("Please type in 1 for a customer to view their portfolio, 2 to trade stocks or 3 to exit the application");
int choice = Integer.parseInt(input.nextLine());
if (choice == 1)
{
System.out.println(mycustomers[cusID].toString());
}
The following is a snippet of what is located in my customer.java which contains setters and getters:
public customer(String n, double b, int Size)
{
Name = n;
balance = b;
stock[] A = new stock[Size];
Portfolio = A;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
I'm not sure if I was able to describe the problem correctly, but if not, let me know if any more information is required.
First, Java naming conventions usually dictate you CamelCase class names (i.e. rename to Customer instead of customer).
I believe your problem is here:
Name == mycustomers[i].getName()
In Java, Strings are objects, and you have to use the equals() method to do a comparison, like so:
Name.equals(mycustomers[i].getName())
If you use the standard ==, the comparison is done on the object's memory location, so unless Name and getName() are literally the exact same String object (unlikely), that will be false. This means the if statement never evaluates to true, cusID remains 0 as you initialized it, and so you print out the first name in the list, Jon.
I would suggest, in addition to changing the above, that you initialize cusID to -1 so you can differentiate between a name that is not found in the list and the selection of the first element in the list. Also, what if two people by the same name are in the list? (Hint: The first one will never be selected in your current implementation.)

Unique User Input Array List

I have a class as defined below:
public class CarHireSystem{
private static final Car[] carList = new Car[100];
private static int carCount = 0;
In this class, I have a menu where the user can add new Car. When they select this option they will be prompted with the following:
System.out.print("Enter car ID: ");
String carID = sc.nextLine();
System.out.print("Enter car description: ");
String cardescription = sc.nextLine();
System.out.print("Enter hire fee: $");
Double hireFee = sc.nextDouble();
sc.nextLine();
carList[carCount] = new Car(carID,carDescription,hireFee);
carCount++;
I would like a way to validate that the car ID entered into the array has not already been entered by the user and print an error message if it has been entered and go back to the main menu. How do I do this without using Hashmap.
Thanks
Check if it is already in the list or not, If not add it.
List<AdventureRide> list = new List();
AdventureRide ride = new AdventureRide(ID,description,admissionFee);
if(!list.contains(ride))
list.add(ride);
If you want to make it with the ID references, you can use a HashMap.
HashMap<Integer, AdventureRide> = new HashMap();
AdventureRide ride = new AdventureRide(ID,description,admissionFee);
if(!hm.containsKey(ID))
hm.put(ID,ride);
You have 2 options:
Go through the array each time you want to enter something and check that the current ID is not present within the array.
Have your AdventureRide override the equals and hashCode methods such that two elements are the same if they have the same ID. Once you have that, replace the array with Set<AdventureRide>. This will make sure you have entries with a unique ID.
I'd recommend you go for option 2, reason being that:
If down the line you need to check some other field, you would just need to change your equals and hashCode methods.
Since the Set is a dynamic data structure, you can add/remove from it without knowing the amount of entries before hand.
You could also use a Set<String> to store the ID, and call contains() or get() with a null check. Or store the AdventureRide instances in a Map<String,AdventureRide>. For example:
Map<String,AdventureRide> adventureMap = new HashMap<String,AdventureRide>();
...
private static final void addNewAdventure()
{
boolean idExists = false;
System.out.print("Enter ID: ");
String id;
do {
id = sc.nextLine();
if(null != adventureMap.get(id)) {
idExists = true;
System.out.println("The ID you entered already exists.\n Please enter a new ID: ");
}
} while(idExists);
System.out.print("Enter story: ");
String description = sc.nextLine();
System.out.print("Enter fee: $");
Double admissionFee = sc.nextDouble();
sc.nextLine();
adventureMap.put(id, new AdventureRide(id,description,admissionFee));
//keep track of objects in array
adventureCount++;
}
boolean exists = false;
for (AdventureRide ar : adventureList) {
if (ar != null && ar.getID().equals(ID)) {
exists = true;
break;
}
}
if (!exists) {
adventureList[adventureCount++] = new AdventureRide(ID, description, admissionFee);
}
Iterate over the array; if an element with the same ID exists, break the for loop and set the exists flag. Then at the end, check if the exists flag has been set. If not, then add the new element into the array.
You can auto generate a unique ID instead of letting user input it. This way, you don't even have to check the duplicated ID.
In your codes, instead of doing this:
adventureList[adventureCount] = new AdventureRide(ID,description,admissionFee);
Change it to:
adventureList[adventureCount] = new AdventureRide(description,admissionFee);
Then in your AdventureRide class:
class AdventureRide
{
private static int count = 0;
private String id;
public AdventureRide(String desc, double adminFee){
autoGenerateID(); //Auto generate formatted ID
}
private void autoGenerateID(){
DecimalFormat fmt = new DecimalFormat("T-00000");
id = fmt.format(count++);
}
}
DecimalFormat to format your ID to specific format. This is of course optional.
Output:
T-00000
T-00001
T-00002
T-00003

Dynamic object creation from user input

I have a two classes, Student containing some basic info, and Course, containing some basic info and an ArrayList of Student objects. I want to dynamically (from user input) populate new instances of both classes. For example, user is prompted for course name, teacher and asked if they want to add students to the course. When done with the course and all the students' information, the loop goes back to asking to add another course.
What I do is, create a Course object and then add students. I manage Student objects by just creating them after collecting user unput with courseInstance.addStudent(new Student(name, age, phone)). It all works well for one course, but how do I manage multiple Course object, dynamically created from input?
Here is a code example:
public static void main(String[] args) {
// TODO code application logic here
Course course = new Course();
Scanner in = new Scanner(System.in);
String ans;
String name;
String gender;
String phone;
int age;
System.out.print("Enter course name: ");
ans = in.nextLine();
course.setName(ans);
System.out.print("Enter teacher name: ");
ans = in.nextLine();
course.setTeacher(ans);
while (true) {
System.out.print("Add student (yes or exit): ");
ans = in.nextLine();
if (ans.equals("exit")) {
break;
}
System.out.print("Enter name: ");
name = in.nextLine();
System.out.print("Enter age: ");
age = in.nextInt();
in.nextLine();
System.out.print("Enter gender: ");
gender = in.nextLine();
System.out.print("Enter phone number: ");
phone = in.nextLine();
course.addStudent(new Student(age, name, phone, gender));
}
in.close();
System.out.print(course);
}
How about having a List of Course objects, and asking (in your while(true) loop) what course each student is registering to?
Create a List which you can populate with courses like this:
ArrayList<Course> courses = new ArrayList<Course>();
When a student enters a name from the course, check if the course exists in the array. If not, add it to the array, else get it from the array and add the student.
Since the Name seems to be the primary attribute to identify a course, you should override the equals(Object o) method of course so it compares the two names of the courses.
public boolean equals(Object o){
return this.getName().equals((Course)o.getName());
}
Then you can simply have a List to store your courses and ask the list if it contains a specific course or not. If not you can add it to the list, otherwise you can add students or teachers to the already existing course.
EDIT: It should be getName() on both courses

Am i even doing this remotely right? Java Methods

Task at hand:Consider a class ratingScore that represents a numeric rating for some thing such as a move. Attributes: A description of what is being rated, The maximum possible rating, rating.
It will have methods to: get rating from ta user, Return the maximum rating posisble, return the rating, return a string showing the rating in a format suitable for display.
a. write a method heading for each method
b. write pre and post conditions for each method
c. write some java statements to test the class
d. implement the class.
I think i did what i was supposed to do, but it is a method and i am not sure that i put enough room for it to be changed much, this is what i have so far.
import java.util.*;
public class MovieRating
{
// instance variables
private String description = " A movie that shows how racism affect our lives and choices";
private int maxRating = 10;
private int rating;
// methods
//precondition: Must have maxRating, rating and description before you post it back to the user.
//rating between 1 and 10, maxRating is set to 10, description of a movie
public void writeOutput()
{
System.out.println("The max rating is: " + maxRating );
System.out.println("Your rating is: " + rating );
System.out.println("The rating for" + description + " is " + rating);
System.out.println("while the max rating was " + maxRating);
}
// PostCondition: Will write maxRating, rating and description to the user.
//Precondition: description, enter the rating
public void readInput()
{
Scanner keyboard = new Scanner(System.in);
System.out.println("What would you rate the movie \"American History x\" out of ten");
System.out.println(description);
rating = keyboard.nextInt();
}
//postcondition: rating will be set to user's input for the movie American History x.
}
This is my Tester program.. not much so far
public class MovieRatingTester
{
public static void main(String[] args)
{
//object of the class MovieRating
MovieRating rating1 = new MovieRating();
rating1.readInput();
rating1.writeOutput();
}
}
SO did i cover what was told to cover? i think i did but i think i did it the wrong way, let me know please.
Ok, my point of view is:
Your class, MovieRating is missing some basic elements of OOP, and that is what I think you suppose to learn in this homework.
The first element missing is a constructor method, what you did is automatically assigning each new MovieRating the same description. The job of the constructor function is giving a unique values to the Object when it first built in the system.
The constructor method is special, it is public and has the exact same name is the class, as we said, in this method you suppose to assign values to your object variables.
the second thing will be to put getters/setters, these are methods who has access to your private values and will be used to assign/get the values from them. Note the use of them in the code:
import java.util.*;
public class MovieRating
{
// instance variables
private String description;
private int maxRating;
private int rating;
/*This is the constructor
Note the use of .this - the expression is used to call the class form withing
itself*/
public MovieRating(String description, int maxRating, int rating) {
this.setDescription(description);
this.setMaxRating(maxRating);
this.setRating(rating);
}
/*These are the getters and setters - get is used for getting the value
and set is used for assigning a value to it*/
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getMaxRating() {
return maxRating;
}
public void setMaxRating(int maxRating) {
this.maxRating = maxRating;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
//This is a method for the printing commands - notice the use of the get methods//
public void printRatings()
{
System.out.println("The max rating is: " + this.getMaxRating() );
System.out.println("Your rating is: " + this.getRating() );
System.out.println("The rating for" + this.getDescription() + " is " +
this.getRating());
System.out.println("while the max rating was " + this.getMaxRating();
}
// PostCondition: Will write maxRating, rating and description to the user.
/*Precondition: description, enter the rating
Note the use of this.setRating()*/
public void readInput()
{
Scanner keyboard = new Scanner(System.in);
System.out.println("What would you rate the movie \"American History x\" out of ten");
System.out.println(description);
this.setRating(keyboard.nextInt());
}
//postcondition: rating will be set to user's input for the movie American History x.
}
Using the constructor, you can create a different rating from your tester program
MovieRating rating1 = new MovieRating("description 1", 10, 5);
MovieRating rating2 = new MovieRating("description 2", 9, 7);
You should not ask / print the data from the Ratings class. These ratings can come from user input, but also from database, web, etc.
1 Add getters and setters for properties of MovieRating
2 Pass the read and write methods to the main. Something like
System.out.println("The rating for the movie |" + rating1.getTitle() + "| is " + rating1.getRating());
3 You are not aggregating ratings to a movie. You can't have two rating to the same movie (v.g., by different users) together. Convert the rating attribute into a Vector to solve it. Change setRating for addRating
There are many other things, but obviously this is a starters exercise and I do not want you to get confused. Work on these issues and check with your teacher.
Java (and OO in general) is all about abstractions. You want to keep your objects as general as possible so that you extend your programs functionality without modifying existing code. This may be beyond what your professor was looking for but here are my suggestions:
1) Rating - separate this into its own class
Again, the rating is totally separate from the movie - songs can have ratings, tv shows can have ratings. Today ratings can be 1-10, tomorrow ratings can up thumbs up or thumbs down, etc. A Movie "has a" rating. Let Rating decide how to prompt the user and how to display itself.
2) Now that you have a separate Movie class, I would take away the hard-coded title, description in my Movie class (this will let me create many movies and rate them).
Then I would eliminate System.out.println in writeOutput method (you can pass in the OutputStream to the function)
By hard-coding in System.in you are forcing implementation. What if tomorrow your professor says "now, instead of printing to the console, print to a file or a database"? You have to modify the code. Actually, instead of writeOutput, I would override the toString method that all Objects have and then just call System.in(movie.toString()) in main.
3) Your test method doesn't "test" anything - it is just executing a statement. Typically a test method will simulate input, execute the statements, and check for the proper state at the end. A good way to signal that the state is improper (if your test fails, like maybe your Movie Rating is -1), then you throw an exception.
4) This is un-OO related and just a preference, but I would put both Pre and Post conditions before the methods. This just makes it easier to find in my opinion.
The idea of OO is that you separate responsibilities/concerns into separate classes. Each class is responsible for itself. This helps to keep your code more flexible and maintainable. Good luck on the assignment!

Categories