JOptionPane not displaying all items from ArrayList - java

I am trying to write a program that will create a food order consisting of food items displayed from a menu. Each item is selected and given a certain quantity. I want to display the items that I select in a JTextField but it has not been working correctly.
There are a few problems that I have ran into and cannot seem to figure out,
The JOptionPane is supposed to display all of the items that I added to the deli arraylist, but it only displays the first one which is Nachos.
My getTotalPrice method is not properly calculating the cost and I'm not entirely sure why.
I want the program to determine if an item is already present in the Arraylist and add to the quantity if it does, and if not then add a new entry to the arraylist. However, it always adds a new item, regardless of if it exists already.
The following is my are all of my class files.
import java.util.ArrayList;
public class Menu {
private final ArrayList<Item> menu;
public Menu() {
menu = new ArrayList<>();
}
public void addItem(Item item) {
menu.add(item);
}
public Item getItem(int itemNo) {
if (menu.size() > itemNo) {
return menu.get(itemNo);
}
return null;
}
#Override
public String toString() {
for (int i = 0; i < menu.size(); i++) {
return String.format("%s: %s \n",i+1, menu.get(i));
}
return null;
}
}
public class Item {
private final String name;
private final double price;
public Item(String name, double price) {
this.name = name;
this.price = price;
}
public double getPrice() {
return price;
}
#Override
public String toString() {
return String.format("Name %s # Price $%s", name, price);
}
public boolean equals(Item item) {
return item.name.equals(item.name);
}
}
public class ItemQty {
private final Item item;
private final int quantity;
public ItemQty(Item item, int quantity) {
this.item = item;
this.quantity = quantity;
}
public Item getItem() {
return item;
}
public int getQuantity() {
return quantity;
}
#Override
public String toString() {
return String.format("%s - %s\n", quantity, item);
}
public boolean equals(ItemQty itemQty) {
return itemQty.getItem().equals(itemQty.getItem());
}
}
import java.util.ArrayList;
public class Order {
private final ArrayList<ItemQty> order;
public Order() {
order = new ArrayList<>();
}
public void addToOrder(ItemQty itemQty) {
if (order.contains(itemQty)) {
int amount = itemQty.getQuantity();
amount += 1;
}
else
order.add(itemQty);
}
public double getTotalPrice() {
for (int index = 0; index < order.size(); index++) {
double price = order.get(index).getItem().getPrice();
int quantity = order.get(index).getQuantity();
double sum = price * quantity;
return sum;
}
return 0;
}
#Override
public String toString() {
String str = "";
for (int index = 0; index < order.size(); index++) {
str += order.get(index).toString() + "\n\n";
}
return str;
}
}
Any help or critiques would be appreciated

My getTotalPrice method is not properly calculating the cost and I'm not entirely sure why.
This is due to the fact that you're returning the value of sum only after the first iteration of your loop
public double getTotalPrice() {
for (int index = 0; index < order.size(); index++) {
double price = order.get(index).getItem().getPrice();
int quantity = order.get(index).getQuantity();
double sum = price * quantity;
return sum;
}
return 0;
}
Something like...
public double getTotalPrice() {
double sum = 0;
for (Order item : order) {
double price = item.getItem().getPrice();
int quantity = item.getQuantity();
sum += (price * quantity);
}
return sum;
}
would work better
The JOptionPane is supposed to display all of the items that I added to the deli arraylist, but it only displays the first one which is Nachos.
Since there is no JOptionPane in your code, it's impossible to know what the issue might be
I want the program to determine if an item is already present in the Arraylist and add to the quantity if it does, and if not then add a new entry to the arraylist. However, it always adds a new item, regardless of if it exists already.
Okay, this is a lot more difficult, because you code doesn't really provide enough support to do it.
There's no way for your code to update the quantity information after the ItemQty is created, you will need to supply a setter of some kind to perform this action (or a add method, to which you pass another ItemQty and it does the job for you)
First, I'd add a new method to ItemQty
public class ItemQty {
//...
public void add(int quantity) {
this.quantity += quantity;
}
}
This just makes it possible to increase the quantity.
Second, I'd change the Order#addToOrder, I'd make it so you had to pass an Item and a quantity to it (other classes don't need to make a ItemQty object in this case). In this method, I'd search for a matching item and either update it or add it to the order.
public class Order {
//...
public void addToOrder(Item item, int quantity) {
List<ItemQty> matches = order.stream().filter((itemQty) -> {
return itemQty.getItem().equals(item);
}).collect(Collectors.toList());
if (matches.size() > 0) {
matches.get(0).add(quantity);
} else {
order.add(new ItemQty(item, quantity));
}
}
Okay, that might have you scratching your head, it does me, but basically, it's just a fancy pancy way for saying...
public void addToOrder(Item item, int quantity) {
ItemQty match = null;
for (ItemQty check : order) {
if (check.getItem().equals(item)) {
match = check;
break;
}
}
if (match != null) {
match.add(quantity);
} else {
order.add(new ItemQty(item, quantity));
}
}

Related

How to put class field into method argument to avoid code repeat

I am currently solving this issue. For example. I have two classes. One for item and second for some kind of records of these items. What I need to do, if I want to have a few methods for get average of different kind from all items in collection. In my example, there is average of price, mass and volume. The methods are repetitive and the only one different thing is the getter. So, is there any option, how to have one private method for counting and another three public, that will use this one private method and somehow put the field as argument?
Item class
public class Item {
private double price;
private double mass;
private double volume;
public double getPrice() {
return price;
}
public double getMass() {
return mass;
}
public double getVolume() {
return volume;
}
}
Stock class
package model;
import java.util.ArrayList;
import java.util.List;
public class Stock {
private List<Item> items;
public Stock() {
items = new ArrayList<>();
}
public double getAveragePrice() {
double sum = 0;
if (!items.isEmpty()) {
for (Item item : items) {
sum += item.getPrice();
}
return sum / items.size();
}
return sum;
}
public double getAverageMass() {
double sum = 0;
if (!items.isEmpty()) {
for (Item item : items) {
sum += item.getMass();
}
return sum / items.size();
}
return sum;
}
public double getAverageVolume() {
double sum = 0;
if (!items.isEmpty()) {
for (Item item : items) {
sum += item.getVolume();
}
return sum / items.size();
}
return sum;
}
}
As Johannes Kuhn proposed in a comment, you can pass the getter as a ToDoubleFunction<Item> to your calculation method:
private double calcAverage(ToDoubleFunction<Item> getter) {
double sum = 0;
if (!items.isEmpty()) {
for (Item item : items) {
sum += getter.applyAsDouble(item);
}
return sum / items.size();
}
return sum;
}
public double getAveragePrice() {
return calcAverage(Item::getPrice);
}
You can then reuse the calculation:
public double getAverageMass() {
return calcAverage(Item::getMass);
}
public double getAverageVolume() {
return calcAverage(Item::getVolume);
}
Here is a solution using stream API
public double getAverageMass() {
return calcAverage(Item::getMass);
}
public double getAverageVolume() {
return calcAverage(Item::getVolume);
}
private double calcAverage(ToDoubleFunction<Item> getter) {
return items.stream().mapToDouble(getter).average().orElse(0);
}

required boolean found no arguments [duplicate]

This question already has answers here:
required: double [] found: no arguments
(4 answers)
Closed 6 years ago.
hoping to find a solution before i put my head through my monitor.
What I am trying to do is use a boolean to make a sell function.
basically I want it not to sell stock if there is less than 0 (print error message)
if there is i want to +1 to numSold and -1 to numInStock.
when i try im getting an error
"method sellCopy in class item cannot be applied to given types; required boolean; found no arguments reason actual and formal argument list differ in length"
public abstract class Item
{
private String name;
private double price;
private int numInStock;
private int numSold;
public Item(String inName, double inPrice)
{
name = inName;
price = inPrice;
numInStock = 0;
numSold = 0;
}
public String getName()
{
return name;
}
public double getPrice()
{
return price;
}
public int getNuminStock()
{
return numInStock;
}
public int getNumSold()
{
return numSold;
}
public void receiveStock(int amount)
{
numInStock = numInStock + amount;
}
public boolean sellCopy(boolean sellCopy)
{
if (numInStock <= 0)
{
sellCopy = true;
numSold = numSold +1;
numInStock = numInStock -1;
return true;
}
else
{
sellCopy = false;
System.out.println("Stock unavalable");
return false;
}
}
}
public class Game extends Item
{
private int MaxPlayers;
public Game(String inName, int inMaxPlayers, double inPrice)
{
super(inName, inPrice);
MaxPlayers = inMaxPlayers;
}
public String toString()
{
return " Game " + super.toString() + " Maximum Player: " + MaxPlayers + "\n";
}
import java.util.*;
public class Shop
{
private ArrayList<Item> items = new ArrayList<Item>();
public boolean addItem(Item newItem)
{
if (!findItem(newItem.getName()))
{
items.add(newItem);
return true;
}
else
{
System.out.println(" Error - an item with that name " +newItem.getName() + " already exists");
return false;
}
}
public boolean findItem(String searchName)
{
for (Item nextItem : items)
{
//might be searchName//
if (searchName.equals(nextItem.getName()))
{
System.out.println(nextItem);
return true;
}
}
return false;
}
public void listItems()
{
System.out.println("The shop contains the following items***\n");
for (Item nextItem : items)
{
System.out.println(nextItem);
}
}
public void calcTotalSales()
{
double total = 0;
for (Item nextItem : items)
{
total += nextItem.getNumSold() * nextItem.getPrice();
}
System.out.println("****The total number sold is worth $" + total);
System.out.println("****");
}
}
public class test
{
public static void main (String args[])
{
//create the shop
Shop myShop = new Shop();
//create a Game and add it to the shop
Game game1 = new Game("Chess", 2, 39.95);
myShop.addItem(game1);
//order and get stock
game1.receiveStock(5);
//sell some items
game1.sellCopy();
//the bastard right here//
//print information about shop
myShop.calcTotalSales();
//test error conditions
Game game2 = new Game("Chess", 2, 39.95);
myShop.addItem(game2); //should fail as a Chess item is already in the shop
//eg2.sellCopy();
}
}
If you look at the code,
game1.sellCopy();
That sellCopy method needs a boolean. You need to pass it.
game1.sellCopy(true);// for example. Pass your actual value.

Java - Scanning Items in an ArrayList

I have a class which creates a 'Purchase' object. This object can be recorded to an ArrayList 'purchaseList' using the recordItem() method. However, I want to create a function that can return a specific Purchase object given an itemNo integer, I have shown my code so far in getPurchase() but am having trouble getting it working.
public class Purchase {
private String name;
private double price;
private int itemNo;
private int sort;
private ArrayList purchaseList = new ArrayList();
public Purchase(String name, double price, int itemNo, int sort) {
this.name = name;
this.price = price;
this.itemNo = itemNo;
this.sort = sort;
}
public void recordItem(int itemNumber, String description, double unitPrice, int sort) {
Purchase newPurchase = new Purchase(description, unitPrice, itemNumber, sort);
purchaseList.add(newPurchase);
}
public int getItemNo() {
return itemNo;
}
public Purchase getPurchase(int itemNumber) {
for(int i = 0; i < purchaseList.size(); i++) {
if(purchaseList[i].getItemNo() == itemNumber) {
return purchaseList[i];
}
else return 0;
}
}
}
purchaseList[i] is valid when you work with arrays.
When working with List objects, to retrieve the ith element, you have to invoke the List.get(int index) method. Like this:
purchaseList.get(i)
And so, your method has to be refactored to:
public Purchase getPurchase(int itemNumber) {
for(int i = 0; i < purchaseList.size(); i++) {
if(purchaseList.get(i).getItemNo() == itemNumber) {
return purchaseList.get(i);
}
else return 0;
}
}
Also, in order to avoid casting from Object to Purchase, you have to make your List generic.
private List<Purchase> purchaseList = new ArrayList<Purchase>();
This way the compiler will ensure that the objects you add to the list are of type Purchase and will not force you to cast them to something specific when being got.
Change your purchaseList[i].getItemNo() to purchaseList.get(i).getItemNo()
Your getPurchase() method logic is incorrect. You shouldn't exit after the first condition is not met.
Try changing it like this:
// Change the declaration like this
private List<Purchase> purchaseList = new ArrayList<Purchase>();
// And change the method like this:
public Purchase getPurchase(int itemNumber) {
for(Purchase purchase : purchaseList) {
if(purchase.getItemNo() == itemNumber) {
return purchase;
}
}
return null;
}
Also recordItem() and getPurchase() don't look like they belong inside the Purchase class.

Subclasses and Superclasses

I'm trying to build a program that has certain requirements, the main being I have a class, and then make a subclass that adds a feature. I create the class DVD, and then I create the subclass.
I'm adding a method to add the year to the list, as well as a restocking fee which will be added to the final inventory value that prints. I built the subclass, created the overriding methods, but it is not being added to the output displayed. Not only that, but it is placing the input year in the wrong place. I am not getting any errors, it just acts like the subclass doesn't exist, even though my DVD class says that some of the methods are being overridden.
I'm thinking I must be missing something where I am supposed to call the new method, and maybe I read the resource wrong, but it sounded like I only needed to call the DVD class, and the methods I wanted overridden would be overridden automatically. I'd prefer to just add this information to the superclass, but it is a requirement for an assignment.
So I'm wondering how do I actually go about calling these override methods when I need them to add these new features? I keep seeing resources telling me how to create them, but not actually implement them.
From my main method, I call the dvd class and then print it. however, it only prints what's in the original dvd class, except for the odd addition of adding the year to where the product ID should be.
public class DVD {
String name;
int id;
int items;
double cost;
//default constructor
public DVD() {
name = "";
id = 0;
items = 0;
cost = 0.0;
}//end default constructor
//constructor to initialize object
public DVD(String dvdName, int itemNum, int quantity, double price) {
name = dvdName;
id = itemNum;
items = quantity;
cost = price;
}//end constructor
//method to calculate value
public double getInventoryValue() {
return items * cost;
}
//method to set name
public void setdvdName(String dvdName){
this.name = dvdName;
}
//method to get name
public String getName(){
return name;
}
//method to set id
public void setitemNum( int itemNum){
this.id = itemNum;
}
//method to get id
public int getId(){
return id;
}
//method to set items
public void setquantity(int quantity){
this.items = quantity;
}
//method to get items
public int getItems(){
return items;
}
//method to set cost
public void setprice( double price){
this.cost = price;
}
//method to get cost
public double getCost(){
return cost;
}
/**
*
* #return
*/
public String toString() {
return "DVD Name: " + getName() +
"ID: " + getId() +
"Items: " + getItems() +
"Cost: " + getCost() +
"Total Value: " +getInventoryValue();
}
}
-
public class ExtendedDVD extends DVD{
double restockFee;
int year;
public ExtendedDVD(){
year = 0;
}
public ExtendedDVD(int year) {
this.year = year;
}
public void setRestockFee(){
this.restockFee = 0.05;
}
public double getRestockFee(){
return restockFee;
}
public void setYear(){
this.year = 0;
}
public int getYear(){
return year;
}
#Override
public double getInventoryValue(){
double value1 = super.getInventoryValue();
double value = restockFee * value1;
double totalInventoryValue = value + super.getInventoryValue();
return totalInventoryValue;
}
#Override
public String toString(){
return super.toString() + "Year" + getYear();
}
}
}
public class Inventory {
DVD[] inventory = new DVD[5];
int current = 0;
private int len;
public Inventory(int len){
inventory = new DVD[len];
}
public double calculateTotalInventory() {
double totalValue = 0;
for ( int j = 0; j < inventory.length; j++ )
totalValue += inventory[j].getInventoryValue();
return totalValue;
}
/**
*
* #param dvd
* #throws Exception
*/
public void addDVD(DVD dvd) throws Exception {
if (current < inventory.length) {
inventory[current++]=dvd;
}else {
Exception myException = new Exception();
throw myException;
}
}
void sort() {
for (DVD inventory1 : inventory) {
len = current;
}
for (int i=0; i<len;i++) {
for(int j=i;j<len;j++) {
if (inventory[i].getName().compareTo(inventory[j].getName())>0) {
DVD temp = inventory[j];
inventory[j] = inventory[i];
inventory[i] = temp;
}
}
}
}
public int getNumberOfItems() {
return current;
}
public void printInventory() {
System.out.println("Current Inventory:");
for(int i=0;i<current;i++) {
System.out.println(inventory[i]);
}
System.out.println("The total value of the inventory is:"+calculateTotalInventory());
}
}
-
public class inventoryprogram1 {
/**
* #param args the command line arguments
*/
public static void main(String[] args){
boolean finish = false;
String dvdName;
int itemNum;
int quantity;
double price;
int year = 0;
Inventory inventory = new Inventory(5);
while (!finish) {
Scanner input = new Scanner(System.in); // Initialize the scanner
System.out.print("Please enter name of DVD: ");
dvdName = input.nextLine();
if (dvdName.equals("stop")) {
System.out.println("Exiting Program");
break;
} else {
System.out.print("Please enter Product Number: ");
itemNum = input.nextInt();
System.out.print("Please enter units: ");
quantity = input.nextInt();
System.out.print("Please enter price of DVD: ");
price = input.nextDouble();
System.out.print("Please enter production year: ");
itemNum = input.nextInt();
DVD dvd= new DVD(dvdName,itemNum,quantity,price);
try {
inventory.addDVD(dvd);
}catch( Exception e) {
System.out.println("Inventory is full.");
break;
}
System.out.println("DVD: " + dvd);
}//end else
}
inventory.sort();
inventory.printInventory();
}
}
if you want to use the new methods that you wrote in ExtendedDVD you need to instantiate that class you are still calling the original dvd class so you will still get those methods.
for example
DVD dvd = new DVD(dvdName, itemNum, quantity, price);
and
DVD Dvd = new ExtendedDVD(dvdName, itemNum, quantity, price);
are two different things
also if you look in your main method you are assigning itemNum twice that is why it is showing you the year
In the main method you just instantiate a DVD object, not an ExtendedDVD object.
replace
DVD dvd= new DVD(dvdName,itemNum,quantity,price);
by something like
DVD dvd= new ExtendedDVD(year);
And obviously, you may want another constructor in ExtendedDVD

How to print out the contents of a HashMap in a certain format?

I'm not entirely sure how I would do this, here is my code:
public class PizzaMenu
{
static Map<String,Pizza> namedPizzas= new HashMap<String,Pizza>();
public static void main(String[] args)
{
}
public static void addItem(String name, Pizza pizza)
{
namedPizzas.put(name, pizza);
}
public String printMenu()
{
/*
String menuString="";
for (Every menu item)
{
//Add name of menu item to menuString with carriage return
//Add details of menu item (pizza.getInfo();) to menuString
}
*/
//return menuString
}
}
I would then call System.out.println(PizzaMenu.printMenu()) in another class. The sort of format I'm hoping to achieve is as follows:
/*
* PizzaName
* Details
*
* Next PizzaName in menu
* Details
*
* Next PizzaName in menu
* Details
*
*
*
*/
Am I maybe using the wrong data structure for this type of operation or is there a way of achieving this?
Here is the structure of the Pizza class (apologies for poor formatting):
public class Pizza
{
private double cost;
private Boolean veg;
private PizzaBase base;
private List<PizzaTopping> toppings = new ArrayList<PizzaTopping>();
public Pizza(PizzaBase base, PizzaTopping topping) //Constructor for pizza with 1 topping
{
setBase (base);
toppings.add(topping);
}
public Pizza(PizzaBase base, PizzaTopping topping, PizzaTopping topping2) //Constructor for pizza with 2 toppings
{
setBase (base);
toppings.add(topping);
toppings.add(topping2);
}
public Pizza(PizzaBase base, PizzaTopping topping, PizzaTopping topping2, PizzaTopping topping3) //Constructor for pizza with 3 toppings
{
setBase (base);
toppings.add(topping);
toppings.add(topping2);
toppings.add(topping3);
}
public double getCost()
{
return cost;
}
public void setCost(double cost)
{
this.cost = cost;
}
public PizzaBase getBase()
{
return base;
}
public void setBase(PizzaBase base)
{
this.base = base;
}
public List<PizzaTopping> getToppings()
{
return this.toppings;
}
public String getToppingsInfo()
{
String toppingInfo = "\n";
PizzaTopping t;
for (int i = 0; i<getToppings().size();i++)
{
t = toppings.get(i);
toppingInfo=toppingInfo+t.getInfo();
}
return toppingInfo;
}
public Boolean getVeg()
{
return veg;
}
public void setVeg(Boolean veg)
{
this.veg = veg;
}
public double calculateCost()
{
PizzaTopping p;
//Loop through all ingredients and add their costs to total cost
for (int i = 0; i<toppings.size();i++)
{
p = toppings.get(i);
cost+=p.getCost();
}
cost+=base.getCost(); //Add pizza base cost to total cost
return cost;
}
//Check if pizza is vegetarian depending upon its ingredients
public Boolean isVeg()
{
Boolean toppingCheck =true;
Boolean baseCheck = true;
PizzaTopping t; //Temporary value used to stored toppings being compared in for loop
//Check each topping and check if it's suitable for vegetarians
for (int i =0; i<toppings.size();i++)
{
while (toppingCheck == true)
{
t = toppings.get(i);
if (t.getVeg()==false)
{
toppingCheck = false;
}
}
}
//Check base to see if it's suitable for vegetarians
if (getBase().getVeg()==false)
{
baseCheck = false;
}
//Return value depending on if all ingredients are suitable for vegetarians
if (toppingCheck == true && baseCheck == true)
{
return true;
}
else return false;
}
public String getInfo()
{
String vegInfo;
if (this.isVeg()==true)
{
vegInfo = "Yes";
}
else vegInfo ="No";
return String.format("Toppings:%s\n"+"Base:\n%s"+"\nTotal Cost:\t£%.2f"+"\nSuitable for vegetarians: %s", getToppingsInfo(), getBase().getInfo(), calculateCost(), vegInfo);
//Return list of toppings, Total Price, vegetarian
}
}
Try this:
String menuString="";
for (Map.Entry<String, Pizza> pizzaItem : namedPizzas.entrySet()) {
menuString += pizzaItem.getKey() + "\n";
menuString += "\t" + pizzaItem.getValue().getInfo() + "\n\n";
}
public String printMenu()
{
String s ="";
for (String key: namedPizzas.keySet()){
s+= pizzaItem.getKey() + "\n";
s+= "\t" + pizzaItem.getValue().getInfo() + "\n\n";
}
return menuString
}
To address your question directly:
You need a set of keys. With a set of keys you can also get values. HashMap#keySet should work for this. You can loop through a set using a for each loop.
Then as you said, you need to build your string and return. Putting it together gives you:
public String printMenu()
{
String menuString = "";
for(String key : namedPizzas.keySet())
{
menuString += key + "\n" +
"\t" + namedPizzas.get(key).getInfo() + "\n\n";
}
return menuString;
}
I would also like to suggest a design improvement. You should be overriding the Object#toString method for things like this. The toString method will get automatically called when you try to print the object. This allows you to do: System.out.println(myPizzaMenu); instead of System.out.println(myPizzaMenu.printMenu());
The name printMenu is also misleading, so for that reason it's also bad.
Unfortunately, after switching the map to a list, it still didn't work. An hour later I found the bug causing it all! Thanks for everyone's answers, I will keep these methods in mind when I need to use maps again.
EDIT: Here is the new class structure for reference:
public class PizzaMenu
{
static List<Pizza> namedPizzas = new ArrayList<Pizza>();
public static void main(String[] args)
{
}
public static void addItem(String name, Pizza pizza)
{
pizza.setName(name.toLowerCase());
namedPizzas.add(pizza);
}
public static String printMenu()
{
String menuString="";
Pizza p;
//Collect all pizzas and add their information to string
for (int i =0; i<namedPizzas.size(); i++)
{
p = namedPizzas.get(i);
menuString+=p.getName().toUpperCase()+"\n"+p.getInfo()+"\n\n";
p.resetCost();
}
return menuString;
}
}

Categories

Resources