Updating the value of an object in an arraylist - java

This problem has been bugging me for the last while.. i cant seem to be able to update the stock value of the vehicle that i'm selling. I understand how to search the array and locate the model that the user is looking for but i don't understand how to update the number of that specific model vehicle that are in stock. which is going to be stock - 1 after a purchase.
I have both basic getters and setters for model and stock variables in the Vehicles superclass
Any help is appreciate!
Below is the method of purchasing a car from the driver class
public void purchaseCar()
{
Scanner scan = new Scanner(System.in);
String model, ans;
System.out.println("****Car Purchase Page****");
System.out.println("Enter the model of car you're looking to purchase");
model = scan.nextLine();
for (Vehicles v : list) {
if (v.getmodel().equals(model))
{
System.out.println("Is this the model you want to purchase?");
ans = scan.nextLine();
if (ans.equals("yes")) {
System.out.println("Okay! Your order is being processed");
Vehicles.setStock() = stock - 1;
}
else {
System.out.println("not working");
}
}
}
}

You're almost there.
Change:
Vehicles.setStock() = stock - 1;
to:
v.setStock(v.getStock() - 1);
As clarification, this is the same as:
int stock = v.getStock(); // Get the current stock value of 'v'
int newStock = stock - 1; // The new stock value after the purchase
v.setStock(newStock); // Set the new stock value

You are not invoking the Vehicles.setStock() on the object you want to update. And in addition this method doesn't receive any parameter to update the new stock.
You should call the method on the instance you want to update passing it the new value of the stock.
Try this
v.setStock(v.getStock() - 1);
If it seems strange to you to use the v.getStock() to build the parameter you can create a new method within your vehicle class.
class Vehicles{
int stock;
public void consumeOne(){
stock = stock -1;
}
}
And then you can call this new method in the for statement
for (Vehicles v : list) {
if (v.getmodel().equals(model)){
ans = scan.nextLine();
if (ans.equals("yes")) {
v.consumeOne();
}else {
System.out.println("not working");
}
}
}

Related

I'm working on an enrolment register. I'm struggling with the following method RemoveMember()

public void EnrollMember() {
Request.instance().setMemberName(getName("Enter member name"));
Request.instance().setMemberAddress(getName("Enter address"));
Request.instance().setMemberPhone(getName("Enter phone"));
Request.instance().setFeePaid(getName("Enter the fee paid"));
Result result = store.addMember(Request.instance());
if (result.getResultCode() != Result.OPERATION_COMPLETED) {
System.out.println("Could not add member");
} else {
System.out.println(result.getMemberName() + "'s id is " + result.getMemberId());
}
}
public void addProduct() {
Request.instance().setProductId(getName("Enter Product ID"));
Request.instance().setProductName(getName("Enter product Name"));
Request.instance().setProductPrice(getName("Enter product price"));
Request.instance().setProductReorder(getName("Enter the product reorder amount"));
Result result= store.addProduct(Request.instance());
if (result.getResultCode() != Result.OPERATION_COMPLETED) {
System.out.println("Could not add product");
} else {
System.out.println(result.getProductName() + "'s id is " + result.getProductId());
}
}
public void RemoveMember(){
//If a valid id is received, the corresponding member is removed. The system would need the member's ID for this purpose.
//Only one member is removed when this functionality is invoked
//Data is in a LinkedList
System.out.println("Enter a valid ID");
Scanner input= new Scanner(System.in);
String validId = input.nextLine();
Result result= store.addMember(Request.instance());
if(result.getMemberId().equals(validId)){
System.out.println("Member removed");
}else{
}
}
Since the data are inside LinkedList, you must iterate either way (even if you call result.get(index); or ask result.contains(member); (just remmeber thatthe Member class needs to have correctly overridden the equals() method, otherwise it would not find the member).
Therefore I would use an List#Iterator and when the object is found, you can call iterator.remove(); to remove the object from the list. If it would be possible, I would suggest to use different means of storing the data you want to find/access later using a identifier, for examle a HashMap<String, Member>. Otherwise you are risking performance issues when the list grows larger.
I have tried to adjust your RemoveMember method bellow. Hope this answers you question.
public void RemoveMember() {
//If a valid id is received, the corresponding member is removed. The system would need the member's ID for this purpose.
//Only one member is removed when this functionality is invoked
//Data is in a LinkedList
System.out.println("Enter a valid ID");
Scanner input = new Scanner(System.in);
String validId = input.nextLine();
Result result = store.addMember(Request.instance());
// I am assuming a class "Member" and "LinkedList<Member> result" for readability
for (Iterator<Member> iterator = store.iterator(); iterator.hasNext(); ) {
Member m = iterator.next();
if (m.getMemberId().equals(validId)) {
iterator.remove();
}
}
}

How to use an instantiated object into a paramater for the method with use of arrays

I'm finding it hard to use my methods even if I correctly instantiated my objects. Any ideas on where I went wrong?
example: I tried compiling the java file but the error I get is
"incompatible types: String cannot be converted to Books"
I think the problem is my instantiated object is being forced into a string but the problem is I used the correct syntax to call on a string. However, it still doesn't read it as a string and says that the instantiated object cannot be converted to the "Books" class.
I've already searched about it but all they say is the object hasn't been created. However, I checked my code and I already instantiated my object even before putting it into the method parameter.
I even tried to print the object on its own with the specific characteristics and it turned out fine. So I guess it goes right up until it gets put into a method.
One thing I don't understand is that I need that object to be referenced into a method.
Here is my code:
class Books{
String type;
int pages;
Books[] booklist;
int bookcounter = 0;
//Constructor to initialize the object "book"
Books(int input){
if(input == 1){
this.type = "Math";
this.pages = 5;
}
if(input == 2){
this.type = "Physics";
this.pages = 9;
}
if(input == 3){
this.type = "Economics";
this.pages = 20;
}
}
//This method needs to add the instantiated object to the array list
void addbooktype(Books kind){
System.out.println("You chose: " + kind);
System.out.println("Adding to the list...");
booklist[bookcounter++] = kind;
}
void printbooks(){
for(int i = 0; i <= bookcounter; i++){
int y = i+1;
System.out.println("Book #"+ y + "is: " +this.booklist[i].type);
System.out.println("With pages of: " + this.booklist[i].pages);
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int bookchoice;
int choice;
String booktype;
int booknum = 0;
do{
System.out.println("===========Menu===========");
System.out.println("[1] - Pick a book \n[2] - Print book list\n[0] - Exit");
System.out.println("==========================");
System.out.print("Choice: ");
choice = sc.nextInt();
switch(choice){
//Selects and adds a book to the list
case 1:
System.out.println("Choose your book: ");
bookchoice = sc.nextInt();
Books book = new Books(bookchoice);
System.out.println(book.type);
booktype = book.type;
book.addbooktype(booktype);
booknum++;
break;
//Prints the book list
case 2:
System.out.println("List of Books: ");
book.printbooks();
break;
case 0:
System.out.println("Exit");
return;
default: System.out.println("Input not found.");
}
}while(choice!=0);
}
}
The errors I get is on the "book.addbooktype(booktype);"
This is where it bugs me, I printed the objected and even put it into a String container but it still rejects it. I don't know where I went wrong. And when it goes into the method it doesn't read the parameter. Any thoughts?
Your method addbooktype requires a parameter of Books type whereas you wanted a String parameter there
void addbooktype(Books kind){
Your code would work if you would make this slight change:
void addbooktype(String kind){
Edit: As per the comments, it seems I misunderstood the code. That being said, here's what you can do:
Replace
book.addbooktype(booktype);
with
book.addbooktype();
and replace
void addbooktype(Books kind){
System.out.println("You chose: " + kind);
System.out.println("Adding to the list...");
booklist[bookcounter++] = kind;
}
with
void addbooktype(){
System.out.println("You chose: " + this.kind);
System.out.println("Adding to the list...");
booklist[bookcounter++] = this;
}
This would add the currently calling object to your array and allow you to use it later.
The issue is that your method accepts Object of Class Book only. However when you are calling that function
book.addbooktype(booktype);
You are giving it type String (In your book class type is String variable). To fix that you either need to pass book object or change the method itself
Passing the book object:
Books book = new Books(bookchoice);
book.addbooktype(book);
and in function you can do something like this
void addbooktype(Books book) {
System.out.println("You chose: " + book.type);
System.out.println("Adding to the list...");
booklist[bookcounter++] = book;
}
(Added Later) Using This:
This approach also utilizes the object however it is better than the approach described above. Instead of passing the object as a parameter which is redundant you can use java word this.
According to java docs Using the this Keyword
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.
So when you call function
book.addbooktype(book);
^ and ^ are same
| |
Inside the method addbooktype
void addbooktype(Books book) {
this and book would also be same.
}
so instead you could do this
book.addbooktype();
and addbooktype would be
void addbooktype() {
System.out.println("You chose: " + this.type);
System.out.println("Adding to the list...");
booklist[bookcounter++] = this;
}
An example where passing object and this would be useful is when you have to compare objects. Lets say you have two objects book1 and book2. You would do something like this
int compareResult = book1.compareTo(book2);
Your method would be
public int compareTo(Book book) {
Now here this would be book1
and book would be book2
Also keep in mind this.type would be same as type. type and this.type are both
referring to same object i.e who we called function on (book1).
}
Changing the function:
or you can just change you function like this though I suggest you pass the object itself. If you just pass the String you won't be able to store it in Books[] booklist
void addbooktype(String type) {
System.out.println("You chose: " + type);
System.out.println("Adding to the list...");
// The line below will give error unless you change Books[] booklist;
// to String[] booklist;
booklist[bookcounter++] = kind;
}

How do I not allow an already entered String in my ArrayList to not be added a second time [duplicate]

This question already has answers here:
Add item only once in custom ArrayList
(3 answers)
Closed 4 years ago.
I have a banking program with an enter customer, and balance method. The method adds a String and a double to my accounts ArrayList, if the name Sam for example is inputted, I want to stop that name from being inputted again, as currently it creates two separate Strings and balances for Sam and when withdrawing/depositing both are modified since I check the name/String to get the right account.
class Bank {
ArrayList<Account> accounts = new ArrayList<Account>();
public void enterCustomers() {
String name = "";
double balance;
System.out.println("Enter customer names or q to quit entering names");
while (true) {
name = MyConsole.getString("Enter a customer name: ");
if (name.equals("q")) {
break;
}
balance = MyConsole.getDouble("Enter opening balance: ");
accounts.add(new Account(name, balance));
}
}
There are many ways of doing this. Here's a way that requires the least modification to your existing code that I can think of:
name = MyConsole.getString("Enter a customer name: ");
if (name.equals("q")) {
break;
}
if (accounts.stream().anyMatch(x -> x.getName().equals(name))) {
System.out.println("This name already exists!");
continue;
}
balance = MyConsole.getDouble("Enter opening balance: ");
accounts.add(new Account(name, balance));
Alternatively, override equals and hashCode in Account, and store them in a HashSet<Account>. You can then check whether something is already in the set at a lower time complexity.
// in your Account class
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Account account = (Account) o;
return name.equals(account.name);
}
#Override
public int hashCode() {
return name.hashCode();
}
// in Bank class
HashSet<Account> accounts = new HashSet<>();
public void enterCustomers() {
String name = "";
double balance;
System.out.println("Enter customer names or q to quit entering names");
while (true) {
name = MyConsole.getString("Enter a customer name: ");
if (name.equals("q")) {
break;
}
balance = MyConsole.getDouble("Enter opening balance: ");
if (!accounts.add(new Account(name, balance))) {
System.out.println("This customer already exists!");
}
}
}
Are you set on using an Array with Accounts?
Other data structures exist, such as the Set That already filter duplicate entries. Set checks the equals method of the objects being inserted against the elements in the Set. In this case that means you would have to implement an equals method in your Account class, that checks if the names of the account are equal.
With java 8 you can do this
boolean nameExists = accounts.stream().anyMatch(account-> "name".equals(account.getName()));
or another approach would be storing name and balance as key value pairs in HashMap, it has a method containsKey to check for the key existence.
Thank you everyone for commenting! I should have mentioned I'm in my first semester of computer science so everything's still very new to me, but now I've got some more stuff to study up on haha. I decided to go with the for loop suggested by Carlos for simplicity sake.
for (Account acc : accounts) {
if (acc.getName().equals(name)) {
System.out.println("That name already exists, please enter a different one.");
continue;
}
If you dont want to use duplicate values then go with Set interface which is a part java.util and extends java.util.Collection interface. It does not allow the use of duplicate elements and at max can accommodate only one null element.
For more reference check the following link
Set in java

Java target/select class/object - confused (sorry for bad title)

What I have below is producing the desired results by print some employee details along with weekly / monthly wages as appropriate.
However I understand that I should not be inputting data in the constructor as I've done.
I need to prompt for a hours worked value only for "PartTimeEmployees", just not the way I've done it.
I've tested with For-Each loops, Enhanced For loops and using the instanceOf operator.
If I could get some guidance/hints or examples of how to accomplish what is currently being done in the constructor, but in the TestEmployee class instead that would be great.
Mostly I'm not sure how to even describe what I'm trying to achieve. This hinders Googling somewhat. (Help with a better title would also be great)
Thanks in advance.
public class TestEmployee
{
public static void main(String[] args)
{
int size;
Employee[] employees = new Employee[4];
employees[0] = new FullTimeEmployee("Jane", 26000);
employees[1] = new PartTimeEmployee("Jack");
employees[2] = new FullTimeEmployee("Lucy", 52000);
employees[3] = new PartTimeEmployee("Lenny");
for(int i = 0; i < employees.length; i++)
{
employees[i].print();
}
}
}
Class: PartTimeEmployee - Constructor:
public PartTimeEmployee(String thisName)
{
super(thisName);
System.out.println("Please enter the number of hours worked by " + thisName + ": ");
numHours = keyboard.nextInt();
setHours(numHours);
}
If I get your question, below might fit with your need -
First of all create generic Employee class -
class Employee {
private String name;
private int workingHours;
private final boolean IS_PART_TIME_EMP;
public Employee(String name, int workingHours) {
this.name = name;
this.workingHours = workingHours;
this.IS_PART_TIME_EMP = false;
}
public Employee(String name) {
this.name = name;
this.IS_PART_TIME_EMP = true;
}
public String getName() {
return name;
}
public int getWorkingHours() {
return workingHours;
}
public void setWorkingHours(int workingHours) {
this.workingHours = workingHours;
}
public boolean isPartTimeEmployee() {
return IS_PART_TIME_EMP;
}
}
Now you can use it as per your requirement.
Employee[] employees = new Employee[4];
employees[0] = new Employee("Jane", 26000);
employees[1] = new Employee("Jack");
employees[2] = new Employee("Lucy", 52000);
employees[3] = new Employee("Lenny");
Scanner sc = new Scanner(System.in);
for (Employee employee : employees) {
if(employee.isPartTimeEmployee()) {
System.out.println("Please enter working hours by " + employee.getName() + ": ");
int numHours = sc.nextInt();
employee.setWorkingHours(numHours);
}
}
Constructor is not meant for user input.Its main intention is to initialize object of that class.
Instead of doing that in constructor,you can try something like this
employees[1] = new PartTimeEmployee("Jack");
System.out.println("Please enter the number of hours worked by " + employees[1].getName()+ ": ");
numHours = keyboard.nextInt();
employees[1].setHours(numHours);
You most likely will have some logical main loop in your program, like
while(!quit) {
// 1. ask if you want to add part time or full time employee
// 2. ask proper questions
// 3. call correct constructor
}
Writing such small pseudo code algorithm should be self explanatory and get you going.
Step one: presentation of options available for user and reading user input.
Step two: performing actions depending on user input from step 1
Step three: final call to proper constructor depending on results from steps 1 and 2
If I understood your question correctly (which I'm really not sure of) you want to prompt for the employee data in the main method.
In that case I'd use a loop and query the following things:
name of the employee
does the employee work full time? (y/n)
if yes: what is the wage? (assume hours = whatever a full time employee works a day)
if no: how many hours? (and probably the hourly wage as well)
Then use that information to construct an Employee object (I don't see any need for the subclasses here).

Java - Add an object to an arraylist, then adding another to the arraylist causes the first element to be overwritten

I'm currently doing my third year programming project and its a folio tracker. :/ I have crated Stock_API and Portfolio_API interfaces (and implementations of them) and a GUI class which when instantiated takes two parameters as so:
public GUI(Portfolio_API p, Stock s){
tempPort = p;
tempStock = s;
}
I use this constructor as a way of getting implementations of these interfaces into the GUI without exposing the implementation to the GUI (which is one of the main objectives of this project). A portfolio object has a name(string) and an ArrayList. A stock object has a ticker symbol(string), a stock name(string), a share value(float), a number of shares(int) and a value of holding(float).
In the GUI i have a portCollection array list which holds objects of type portfolio_API and this is so the system can keep track of multiple portfolios. Also as mentioned in the block of code above has a tempStock and tempPort object.
Sorry to give u so much detail about the program but i thought it best so i could get the context across. Anyway, the problem at hand. I have a method which uses the GUI to get a ticker symbol, a stock name and a number of shares and adds the stock to the current portfolio open(each portfolio has its own tab). The method looks like this:
public void addStock() {
int num_shares = 0;
float dailyChange = 0.0f;
float stockValue = 0.0f;
boolean succeed = true;
// GUI gets information of stock from user
String ticker = JOptionPane.showInputDialog(frame,
"Enter the ticker symbol:");
String stockName = JOptionPane.showInputDialog(frame,
"Enter the Stock name:");
try {
num_shares = Integer.parseInt(JOptionPane.showInputDialog(frame,
"Enter the number of shares:"));
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(frame,
"Number of shares was not an integer. Try again");
succeed = false;
}
// If parsing was successful...
if (succeed) {
tempStock.setTicker(ticker);
tempStock.setNumberOfShares(num_shares);
tempStock.setStockName(stockName);
// Fetches newest value using the current ticker symbol
boolean succeedUpdate = tempStock.updateShareValue();
if (succeedUpdate) {
tempStock.calculateValueOfHolding();
// Adds to the current portfolio...
String tabName = tabbedPane.getTitleAt(tabbedPane
.getSelectedIndex());
System.out.println(tabName);
findPortfolio(tabName).addStock(tempStock);
findPortfolio(tabName).sort();
// ...Then adds it to the table
JPanel j = (JPanel) tabbedPane.getSelectedComponent()
.getComponentAt(0, 0);
JViewport v = ((JScrollPane) j.getComponent(0)).getViewport();
JTable table = (JTable) v.getComponent(0);
float currentTotal = findPortfolio(tabName).getTotal();
// Updates the total label
((JLabel) j.getComponent(1)).setText("Total: " + currentTotal);
Object[] newStock = { tempStock.getTicker(),
tempStock.getStockName(),
tempStock.getNumberOfShares(),
tempStock.getShareValue(),
tempStock.getValueOfHolding() };
((DefaultTableModel) table.getModel()).addRow(newStock);
}
}
}
When I add more than one stock, the new stock takes place of the old one an effectively overwrites it. I think its the reuse of tempStock that is doing it. Not sure why though as surely if i add the variable to an arraylist it becomes part of that arraylist and needs no association with the tempStock variable?
Methods that are used with the mentioned arraylists :
private Portfolio_API findPortfolio(String name) {
Portfolio_API p = null;
for (int i = 0; i < portCollection.size(); i++) {
if (portCollection.get(i).getName() == name) {
p = portCollection.get(i);
}
}
These two are in the Portfolio class:
#Override
public boolean addStock(Stock_API s) {
if (!doesExist(s)) {
portfolio.add(s);
return true;
} else {
return false;
}
}
#Override
public boolean doesExist(Stock_API s) {
boolean found = false;
for (int i = 0; i < portfolio.size(); i++) {
if (portfolio.get(i).getTicker() == s.getTicker()) {
found = true;
}
}
return found;
}
I've only come here for help because i have hit a brick wall and I really need help. If anyone could give me any suggestions, i'd be eternally in your debt.
Thanks,
Chris
Yes, I think you are right when you say you think it's because you're reusing the tempStock variable. This variable still references the original object so calling setTicker() etc on tempStock also changes the object referenced by your ArrayList because it's the same object. Try reinitialising your tempStock and see if it makes a difference:
// If parsing was successful...
if (succeed) {
tempStock = new Stock(); // or however you instantiate this object
tempStock.setTicker(ticker);
tempStock.setNumberOfShares(num_shares);
tempStock.setStockName(stockName);
Thanks guys for all your input. #oracle certified professor helped with the stock problems after adding an overloaded method for addStock but turned out the same problems plagued portfolio.
What I did was create a makePortfolio method in Portfolio_API to create a new portfolio and return it. That way it avoids any nasty overwrite, gonna add it to stock too just now.
Thanks again guys. Good night! :)

Categories

Resources